diff --git a/Jenkinsfile.split b/Jenkinsfile.split index bde284048d..bae2205498 100644 --- a/Jenkinsfile.split +++ b/Jenkinsfile.split @@ -18,6 +18,7 @@ properties([ booleanParam(name: 'runUnstableTests', defaultValue: true, description: "Whether to run tests in failing group."), booleanParam(name: 'runPerformanceTests', defaultValue: false, description: "Whether to run performance tests."), booleanParam(name: 'runClusterTests', defaultValue: false, description: "Whether to run cluster tests."), + booleanParam(name: 'useOpenApiTestClient',defaultValue: false, description: "Whether to use an autogenerated OpenAPI OkHTTP 3 based REST client for the tests."), booleanParam(name: 'runDeploy', defaultValue: false, description: "Whether to run the deploy steps."), booleanParam(name: 'runDeployTesting', defaultValue: false, description: "Whether to run the testing deploy steps."), booleanParam(name: 'runDocker', defaultValue: false, description: "Whether to run the docker steps."), @@ -68,19 +69,19 @@ final def testPart(partName, current, branches) { // prior to starting the tests, start the docker containers with the db and the testdb-manager sh 'docker login -u $repoUsername -p $repoPassword docker.gentics.com' if (Boolean.valueOf(params.testMaria)) { - sh "mvn -pl :mesh-database-connector-mariadb docker:start -Dskip.mariadb.tests=${noMariadb} " + sh "mvn -pl :mesh-database-connector-mariadb docker:start -Dskip.mariadb.tests=${noMariadb} " } // run the tests - withEnv(["TESTCONTAINERS_RYUK_DISABLED=true", "MESH_CONSISTENCY_CHECKS=" + (Boolean.valueOf(params.consistencyChecks) ? "true" : "false"), "MAVEN_OPTS=-Xmx1g -XX:MaxMetaspaceSize=128m "]) { + withEnv(["TESTCONTAINERS_RYUK_DISABLED=true", "MESH_CONSISTENCY_CHECKS=" + (Boolean.valueOf(params.consistencyChecks) ? "true" : "false"), "MAVEN_OPTS=-Xmx1g -XX:MaxMetaspaceSize=128m ", "MESH_REST_CLIENT_CLASS=" + (Boolean.valueOf(params.useOpenApiTestClient) ? "com.gentics.mesh.test.openapi.OpenAPIMeshRestClient" : "")]) { sh ".jenkins/run-splits.sh includes-${postfix} ${jacoco} ${partName} ${partId}" } } finally { // finally stop the docker containers if (Boolean.valueOf(params.testMaria)) { - sh "mvn -pl :mesh-database-connector-mariadb docker:stop -Dskip.mariadb.tests=${noMariadb} " + sh "mvn -pl :mesh-database-connector-mariadb docker:stop -Dskip.mariadb.tests=${noMariadb} " + } } } - } stash name: "jacoco" + current, includes: "**/jacoco-partial.exec", allowEmpty: true } finally { step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/*.xml']) @@ -216,9 +217,9 @@ stage("Setup Build Environment") { } try { withCredentials([usernamePassword(credentialsId: 'docker.gentics.com', usernameVariable: 'repoUsername', passwordVariable: 'repoPassword'),usernamePassword(credentialsId: 'gentics.gpg', usernameVariable: 'gpgKeyName', passwordVariable: 'gpgKeyPass')]) { - withEnv(["TESTCONTAINERS_RYUK_DISABLED=true", "MESH_CONSISTENCY_CHECKS=" + (Boolean.valueOf(params.consistencyChecks) ? "true" : "false")]) { + withEnv(["TESTCONTAINERS_RYUK_DISABLED=true", "MESH_CONSISTENCY_CHECKS=" + (Boolean.valueOf(params.consistencyChecks) ? "true" : "false"), "MESH_REST_CLIENT_CLASS=" + (Boolean.valueOf(params.useOpenApiTestClient) ? "com.gentics.mesh.test.openapi.OpenAPIMeshRestClient" : "")]) { sh "mvn -fae -Dsurefire.excludedGroups=com.gentics.mesh.test.category.FailingTests,com.gentics.mesh.test.category.ClusterTests -Dmaven.javadoc.skip=true -Dskip.cluster.tests=true -Dmaven.test.failure.ignore=true -Dmesh.container.image.prefix=docker.gentics.com/ -Dskip.mariadb.tests=${noMariadb} -Dskip.hsqlmemory.tests=${noHsqldb} -B -U -e test" - } + } } } finally { step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/*.xml']) diff --git a/api/src/main/java/com/gentics/mesh/etc/config/Format.java b/api/src/main/java/com/gentics/mesh/etc/config/Format.java new file mode 100644 index 0000000000..1733c377a5 --- /dev/null +++ b/api/src/main/java/com/gentics/mesh/etc/config/Format.java @@ -0,0 +1,49 @@ +package com.gentics.mesh.etc.config; + +import org.apache.commons.lang3.StringUtils; + +/** + * OpenAPI output format + */ +public enum Format { + /** + * Yaml + */ + YAML(0), + /** + * JSON + */ + JSON(1); + + private final int level; + + private Format(int level) { + this.level = level; + } + + /** + * Get the filtering int value. + * + * @return + */ + public int getLevel() { + return level; + } + + /** + * Safe parse string value + * + * @param format + * @param defaultValue + * @return + */ + public static Format parse(String format, Format defaultValue) { + if (StringUtils.isNotBlank(format)) { + switch (format.toUpperCase()) { + case "YAML": return YAML; + case "JSON": return JSON; + } + } + return defaultValue; + } +} diff --git a/api/src/main/java/com/gentics/mesh/etc/config/MeshOptions.java b/api/src/main/java/com/gentics/mesh/etc/config/MeshOptions.java index 32c56ddafc..fb1414691e 100644 --- a/api/src/main/java/com/gentics/mesh/etc/config/MeshOptions.java +++ b/api/src/main/java/com/gentics/mesh/etc/config/MeshOptions.java @@ -37,6 +37,7 @@ public abstract class MeshOptions implements Option { public static final String MESH_CLUSTER_INIT_ENV = "MESH_CLUSTER_INIT"; public static final String MESH_LOCK_PATH_ENV = "MESH_LOCK_PATH"; public static final String MESH_LIVE_PATH_ENV = "MESH_LIVE_PATH"; + public static final String MESH_SERVE_OPENAPI_ENV = "MESH_SERVE_OPENAPI"; public static final String MESH_START_IN_READ_ONLY_ENV = "MESH_START_IN_READ_ONLY"; public static final String MESH_INITIAL_ADMIN_PASSWORD_ENV = "MESH_INITIAL_ADMIN_PASSWORD"; public static final String MESH_INITIAL_ADMIN_PASSWORD_FORCE_RESET_ENV = "MESH_INITIAL_ADMIN_PASSWORD_FORCE_RESET"; @@ -152,6 +153,10 @@ public abstract class MeshOptions implements Option { @EnvironmentVariable(name = MESH_MIGRATION_TRIGGER_INTERVAL, description = "Override the migration trigger interval") private long migrationTriggerInterval = DEFAULT_MIGRATION_TRIGGER_INTERVAL; + @JsonProperty(required = false) + @EnvironmentVariable(name = MESH_SERVE_OPENAPI_ENV, description = "Serve OpenAPI specification under `/openapi*` endpoints. Default: true") + private boolean serveOpenApi = true; + @JsonProperty(required = true) @JsonPropertyDescription("GraphQL options.") private GraphQLOptions graphQLOptions = new GraphQLOptions(); @@ -272,7 +277,6 @@ public MeshOptions setMonitoringOptions(MonitoringConfig monitoringOptions) { return this; } - /** * Get the graphql options * @return graphql options @@ -544,6 +548,15 @@ public MeshOptions setPluginUseHttp2(boolean pluginUseHttp2) { return this; } + public boolean isServeOpenApi() { + return serveOpenApi; + } + + @Setter + public void setServeOpenApi(boolean serveOpenApi) { + this.serveOpenApi = serveOpenApi; + } + @JsonIgnore public abstract NativeQueryFiltering getNativeQueryFiltering(); @@ -608,4 +621,24 @@ public void validate(MeshOptions options) { } public abstract boolean hasDatabaseLevelCache(); + + /** + * Get default OpenAPI spec version + * + * @return + */ + public abstract Version getDefaultOpenAPIVersion(); + + /** + * Get default OpenAPI spec format + * + * @return + */ + public abstract Format getDefaultOpenAPIFormat(); + + /** + * Get the comma separated list of plugin, that should provide no API info. Can be null or empty. + * @return + */ + public abstract String getNoApiInfoPlugins(); } diff --git a/api/src/main/java/com/gentics/mesh/etc/config/Version.java b/api/src/main/java/com/gentics/mesh/etc/config/Version.java new file mode 100644 index 0000000000..79cab7a007 --- /dev/null +++ b/api/src/main/java/com/gentics/mesh/etc/config/Version.java @@ -0,0 +1,69 @@ +package com.gentics.mesh.etc.config; + +import org.apache.commons.lang3.StringUtils; + +/** + * OpenAPI specification version + */ +public enum Version { + + /** + * v3.0 + */ + V30(0), + /** + * v3.1 + */ + V31(1); + + private final int level; + + private Version(int level) { + this.level = level; + } + + /** + * Get the filtering int value. + * + * @return + */ + public int getLevel() { + return level; + } + + /** + * Safe parse string value + * + * @param version + * @param defaultValue + * @return + */ + public static Version parse(String version, Version defaultValue) { + if (StringUtils.isNotBlank(version)) { + switch (version.toUpperCase()) { + case "V30": + case "3.0": + return V30; + case "V31": + case "3.1": + return V31; + } + } + return defaultValue; + } + + /** + * Pretty print the version + * + * @return + */ + public String pretty() { + switch(this) { + case V30: + return "3.0"; + case V31: + return "3.1"; + } + return null; + } +} diff --git a/bom/pom.xml b/bom/pom.xml index c97c5e7888..cdf78425b4 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -47,6 +47,8 @@ 4.3.1 2.7.3 1.15.5 + 0.0.1-SNAPSHOT + 5.3.0 @@ -108,6 +110,11 @@ commons-lang3 3.18.0 + + com.gentics + vertx-openapi + ${vertx.openapi.version} + commons-io commons-io @@ -133,7 +140,12 @@ com.squareup.okhttp3 okhttp-jvm - 5.3.0 + ${okhttp.version} + + + com.squareup.okhttp3 + logging-interceptor + ${okhttp.version} @@ -172,7 +184,7 @@ com.google.code.gson gson - 2.8.9 + 2.10.1 @@ -808,9 +820,9 @@ 3.2.0 - jakarta.persistence - jakarta.persistence-api - 3.2.0 + jakarta.persistence + jakarta.persistence-api + 3.2.0 com.squareup.inject @@ -833,9 +845,9 @@ ${hazelcast-hibernate.version} - org.hibernate.orm - hibernate-jcache - ${hibernate.version} + org.hibernate.orm + hibernate-jcache + ${hibernate.version} org.hibernate.orm diff --git a/changelog/src/changelog/entries/2026/03/8685.GPU-2196.enhancement b/changelog/src/changelog/entries/2026/03/8685.GPU-2196.enhancement new file mode 100644 index 0000000000..1a360ad8e5 --- /dev/null +++ b/changelog/src/changelog/entries/2026/03/8685.GPU-2196.enhancement @@ -0,0 +1 @@ +REST API: Along with existing RAML API definition, it is now possible to generate an OpenAPI (aka Swagger) specification for the Mesh REST API. For that, an endpoint `/openapi.yaml` has been provided. \ No newline at end of file diff --git a/common/src/main/java/com/gentics/mesh/rest/impl/InternalEndpointRouteImpl.java b/common/src/main/java/com/gentics/mesh/rest/impl/InternalEndpointRouteImpl.java index bb32e051fb..5ba44c649d 100644 --- a/common/src/main/java/com/gentics/mesh/rest/impl/InternalEndpointRouteImpl.java +++ b/common/src/main/java/com/gentics/mesh/rest/impl/InternalEndpointRouteImpl.java @@ -1,50 +1,21 @@ package com.gentics.mesh.rest.impl; import static com.gentics.mesh.core.rest.error.Errors.error; -import static com.gentics.mesh.http.HttpConstants.APPLICATION_JSON; -import static com.gentics.mesh.http.HttpConstants.APPLICATION_JSON_UTF8; -import static io.vertx.core.http.HttpMethod.DELETE; -import static io.vertx.core.http.HttpMethod.POST; -import static io.vertx.core.http.HttpMethod.PUT; -import static org.apache.commons.lang3.StringUtils.isEmpty; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; +import java.util.Collections; import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.codehaus.jettison.json.JSONObject; -import org.raml.model.MimeType; -import org.raml.model.Response; -import org.raml.model.parameter.FormParameter; -import org.raml.model.parameter.Header; -import org.raml.model.parameter.QueryParameter; -import org.raml.model.parameter.UriParameter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.module.jsonSchema.JsonSchema; import com.gentics.mesh.core.db.Database; import com.gentics.mesh.core.endpoint.admin.LocalConfigApi; import com.gentics.mesh.core.rest.MeshEvent; -import com.gentics.mesh.core.rest.common.RestModel; import com.gentics.mesh.json.JsonUtil; -import com.gentics.mesh.parameter.ParameterProvider; import com.gentics.mesh.rest.InternalEndpointRoute; -import com.google.common.collect.ImmutableSet; import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.Handler; -import io.vertx.core.http.HttpMethod; -import io.vertx.ext.web.Route; import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.handler.PlatformHandler; @@ -52,448 +23,40 @@ /** * @see InternalEndpointRoute */ -public class InternalEndpointRouteImpl implements InternalEndpointRoute { - - private static final Logger log = LoggerFactory.getLogger(InternalEndpointRoute.class); - - private static final Map, String> SCHEMA_CACHE = new ConcurrentHashMap<>(); - - private static final Set mutatingMethods = ImmutableSet.of(POST, PUT, DELETE); - - private Route route; - - private String displayName; - - private String description; - - /** - * Uri Parameters which map to the used path segments - */ - private Map uriParameters = new HashMap<>(); - - /** - * Map of example responses for the corresponding status code. - */ - private Map exampleResponses = new HashMap<>(); - - private Map> exampleResponseClasses = new HashMap<>(); +public class InternalEndpointRouteImpl extends com.gentics.vertx.openapi.metadata.InternalEndpointRouteImpl implements InternalEndpointRoute { - private Set events = new HashSet<>(); - - private String[] traits = new String[] {}; - - private HashMap exampleRequestMap = null; - - private Class exampleRequestClass = null; - - private String pathRegex; - - private HttpMethod method; - - private String ramlPath; - - private final Set consumes = new LinkedHashSet<>(); - private final Set produces = new LinkedHashSet<>(); - - private Map parameters = new HashMap<>(); - - private Boolean mutating; + protected Set events = new HashSet<>(); /** - * Create a new endpoint wrapper using the provided router to create the wrapped route instance. + * Create a new endpoint wrapper using the provided router to create the wrapped + * route instance. * * @param router * @param localConfigApi * @param db */ public InternalEndpointRouteImpl(Router router, LocalConfigApi localConfigApi, Database db) { - this.route = router.route(); + super(router); + setInsecure(false); ReadOnlyHandler readOnlyHandler = new ReadOnlyHandler(localConfigApi, db); route.handler(readOnlyHandler); } @Override - public InternalEndpointRoute path(String path) { - route.path(path); - return this; - } - - @Override - public InternalEndpointRoute method(HttpMethod method) { - if (this.method != null) { - throw new RuntimeException( - "The method for the endpoint was already set. The endpoint wrapper currently does not support more than one method per route."); - } - this.method = method; - route.method(method); - return this; - } - - @Override - public InternalEndpointRoute pathRegex(String path) { - this.pathRegex = path; - route.pathRegex(path); - return this; - } - - @Override - public InternalEndpointRoute produces(String contentType) { - produces.add(contentType); - route.produces(contentType); - return this; - } - - @Override - public InternalEndpointRoute consumes(String contentType) { - consumes.add(contentType); - route.consumes(contentType); - return this; - } - - @Override - public InternalEndpointRoute order(int order) { - route.order(order); - return this; - } - - @Override - public InternalEndpointRoute last() { - route.last(); - return this; - } - - @Override - public InternalEndpointRoute handler(Handler requestHandler) { - validate(); - route.handler(requestHandler); - return this; - } - - @Override - public InternalEndpointRoute subRouter(Router subRouter) { - validate(); - route.subRouter(subRouter); - return this; - } - - @Override - public InternalEndpointRoute validate() { - if (!produces.isEmpty() && produces.contains(APPLICATION_JSON) && exampleResponses.isEmpty()) { - throw new RuntimeException("Endpoint {" + getRamlPath() + "} has no example responses."); - } - if ((consumes.contains(APPLICATION_JSON) || consumes.contains(APPLICATION_JSON_UTF8)) && exampleRequestMap == null) { - throw new RuntimeException("Endpoint {" + getRamlPath() + "} has no example request."); - } - if (isEmpty(description)) { - throw new RuntimeException("Endpoint {" + getPath() + "} has no description."); - } - - // Check whether all segments have a description. - List segments = getNamedSegments(); - for (String segment : segments) { - if (!getUriParameters().containsKey(segment)) { - throw new RuntimeException("Missing URI description for path {" + getRamlPath() + "} segment {" + segment + "}"); - } - } - return this; - } - - @Override - public List getNamedSegments() { - List allMatches = new ArrayList(); - Matcher m = Pattern.compile("\\{[^}]*\\}").matcher(getRamlPath()); - while (m.find()) { - allMatches.add(m.group().substring(1, m.group().length() - 1)); - } - return allMatches; - } - - @Override + @Deprecated public InternalEndpointRoute blockingHandler(Handler requestHandler) { - route.blockingHandler(requestHandler); - return this; - } - - @Override - public InternalEndpointRoute blockingHandler(Handler requestHandler, boolean ordered) { - route.blockingHandler(requestHandler, ordered); - return this; - } - - @Override - public InternalEndpointRoute failureHandler(Handler failureHandler) { - route.failureHandler(failureHandler); - return this; - } - - @Override - public InternalEndpointRoute remove() { - route.remove(); - return this; - } - - @Override - public InternalEndpointRoute disable() { - route.disable(); - return this; - } - - @Override - public InternalEndpointRoute enable() { - route.enable(); - return this; - } - - @Override - public InternalEndpointRoute useNormalisedPath(boolean useNormalisedPath) { - route.useNormalizedPath(useNormalisedPath); - return this; - } - - @Override - public String getPath() { - return route.getPath(); - } - - @Override - public String getRamlPath() { - if (ramlPath == null) { - return convertPath(route.getPath()); - } - return ramlPath; - } - - @Override - public InternalEndpointRoute displayName(String name) { - this.displayName = name; - return this; - } - - @Override - public InternalEndpointRoute description(String description) { - this.description = description; - return this; - } - - @Override - public String getDescription() { - return description; - } - - @Override - public String getDisplayName() { - return displayName; - } - - @Override - public InternalEndpointRoute exampleResponse(HttpResponseStatus status, String description, String headerName, String example, String headerDescription) { - Response response = new Response(); - response.setDescription(description); - exampleResponses.put(status.code(), response); - if (headerName != null) { - Header header = new Header(); - header.setDescription(headerDescription); - header.setExample(example); - Map headers = new HashMap<>(); - headers.put(headerName, header); - response.setHeaders(headers); - } - return this; - } - - @Override - public InternalEndpointRoute exampleResponse(HttpResponseStatus status, String description) { - return exampleResponse(status, description, null, null, null); - } - - @Override - public InternalEndpointRoute exampleResponse(HttpResponseStatus status, Object model, String description) { - Response response = new Response(); - response.setDescription(description); - - HashMap map = new HashMap<>(); - response.setBody(map); - - MimeType mimeType = new MimeType(); - if (model instanceof RestModel) { - String json = ((RestModel) model).toJson(false); - mimeType.setExample(json); - mimeType.setSchema(getSchema(model.getClass())); - map.put("application/json", mimeType); - } else { - mimeType.setExample(model.toString()); - map.put("text/plain", mimeType); - } - - exampleResponses.put(status.code(), response); - exampleResponseClasses.put(status.code(), model.getClass()); - return this; - } - - private String getSchema(Class clazz) { - return SCHEMA_CACHE.computeIfAbsent(clazz, JsonUtil::getJsonSchema); - } - - @Override - public Map> getExampleResponseClasses() { - return exampleResponseClasses; - } - - @Override - public InternalEndpointRoute exampleRequest(String bodyText) { - HashMap bodyMap = new HashMap<>(); - MimeType mimeType = new MimeType(); - mimeType.setExample(bodyText); - bodyMap.put("text/plain", mimeType); - this.exampleRequestMap = bodyMap; - return this; - } - - @Override - public InternalEndpointRoute exampleRequest(Map> parameters) { - HashMap bodyMap = new HashMap<>(); - MimeType mimeType = new MimeType(); - mimeType.setFormParameters(parameters); - bodyMap.put("multipart/form-data", mimeType); - this.exampleRequestMap = bodyMap; - return this; - } - - @Override - public InternalEndpointRoute exampleRequest(RestModel model) { - HashMap bodyMap = new HashMap<>(); - MimeType mimeType = new MimeType(); - String json = model.toJson(false); - mimeType.setExample(json); - mimeType.setSchema(getSchema(model.getClass())); - bodyMap.put("application/json", mimeType); - this.exampleRequestMap = bodyMap; - this.exampleRequestClass = model.getClass(); - return this; - } - - @Override - public InternalEndpointRoute exampleRequest(JSONObject jsonObject) { - HashMap bodyMap = new HashMap<>(); - MimeType mimeType = new MimeType(); - String json = jsonObject.toString(); - mimeType.setExample(json); - bodyMap.put("application/json", mimeType); - this.exampleRequestMap = bodyMap; - return this; - } - - @Override - public InternalEndpointRoute traits(String... traits) { - this.traits = traits; - return this; - } - - @Override - public String[] getTraits() { - return traits; - } - - @Override - public Map getExampleResponses() { - return exampleResponses; - } - - @Override - public HashMap getExampleRequestMap() { - return exampleRequestMap; - } - - @Override - public String getPathRegex() { - return pathRegex; - } - - @Override - public HttpMethod getMethod() { - return method; - } - - @Override - public Map getQueryParameters() { - return parameters; - } - - @Override - public InternalEndpointRoute addQueryParameters(Class clazz) { - try { - ParameterProvider provider = clazz.getConstructor().newInstance(); - parameters.putAll(provider.getRAMLParameters()); - } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { - e.printStackTrace(); - } - return this; - } - - @Override - public InternalEndpointRoute addQueryParameter(String name, String description, String example) { - QueryParameter param = new QueryParameter(); - param.setDescription(description); - if (example != null) { - param.setExample(example); - } - parameters.put(name, param); + super.blockingHandler(requestHandler); return this; } @Override - public InternalEndpointRoute setRAMLPath(String path) { - this.ramlPath = path; - return this; + protected String getJsonSchema(JsonSchema schema) { + return JsonUtil.getJsonSchema(schema); } @Override - public Map getUriParameters() { - return uriParameters; - } - - @Override - public InternalEndpointRoute addUriParameter(String key, String description, String example) { - UriParameter param = new UriParameter(key); - param.setDescription(description); - param.setExample(example); - uriParameters.put(key, param); - return this; - } - - @Override - public int compareTo(InternalEndpointRoute o) { - return getRamlPath().compareTo(o.getRamlPath()); - } - - /** - * Convert the provided vertx path to a RAML path. - * - * @param path - * @return RAML Path which contains '{}' instead of ':' characters - */ - private String convertPath(String path) { - StringBuilder builder = new StringBuilder(); - String[] segments = path.split("/"); - for (int i = 0; i < segments.length; i++) { - String segment = segments[i]; - if (segment.startsWith(":")) { - segment = "{" + segment.substring(1) + "}"; - } - builder.append(segment); - if (i != segments.length - 1) { - builder.append("/"); - } - } - if (path.endsWith("/")) { - builder.append("/"); - } - return builder.toString(); - } - - @Override - public Class getExampleRequestClass() { - return exampleRequestClass; + protected JsonSchema getJsonSchemaObject(Class clazz) { + return JsonUtil.getJsonSchemaObject(clazz); } @Override @@ -502,34 +65,16 @@ public InternalEndpointRoute events(MeshEvent... events) { return this; } - /** - * Return list of events for the endpoint. - * - * @return - */ - public Set getEvents() { - return events; - } - @Override - public boolean isMutating() { - return Optional.ofNullable(mutating) - .orElse(Optional.ofNullable(getMethod()) - .map(mutatingMethods::contains) - .orElse(false)); - } - - @Override - public InternalEndpointRouteImpl setMutating(Boolean mutating) { - this.mutating = mutating; + public InternalEndpointRoute setInsecure(boolean insecure) { + if (insecure) { + setSecuritySchemes(Collections.emptyList()); + } else { + setSecuritySchemes(Collections.singletonList("bearerAuth")); + } return this; } - @Override - public Route getRoute() { - return route; - } - private class ReadOnlyHandler implements PlatformHandler { private final LocalConfigApi localConfigApi; diff --git a/common/src/main/java/com/gentics/mesh/router/CustomRouterImpl.java b/common/src/main/java/com/gentics/mesh/router/CustomRouterImpl.java index fa2f34ad2a..09a1df02a9 100644 --- a/common/src/main/java/com/gentics/mesh/router/CustomRouterImpl.java +++ b/common/src/main/java/com/gentics/mesh/router/CustomRouterImpl.java @@ -38,6 +38,7 @@ public CustomRouterImpl(Vertx vertx, RootRouterImpl root) { * * @return */ + @Override public Router getRouter() { return this.router; } diff --git a/common/src/main/java/com/gentics/mesh/router/PluginRouterImpl.java b/common/src/main/java/com/gentics/mesh/router/PluginRouterImpl.java index a05d945dc8..c33c6de651 100644 --- a/common/src/main/java/com/gentics/mesh/router/PluginRouterImpl.java +++ b/common/src/main/java/com/gentics/mesh/router/PluginRouterImpl.java @@ -1,5 +1,6 @@ package com.gentics.mesh.router; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -23,9 +24,9 @@ public class PluginRouterImpl implements PluginRouter { private static final Logger log = LoggerFactory.getLogger(APIRouterImpl.class); - private Map pluginRouters = new HashMap<>(); + private final Map pluginRouters = new HashMap<>(); - private Router router; + private final Router router; /** * Create a new plugin router. @@ -73,4 +74,13 @@ public void removeRouter(String name) { } } + @Override + public Map pluginRouters() { + return Collections.unmodifiableMap(pluginRouters); + } + + @Override + public Router getRouter() { + return router; + } } diff --git a/common/src/main/java/com/gentics/mesh/router/ProjectsRouterImpl.java b/common/src/main/java/com/gentics/mesh/router/ProjectsRouterImpl.java index 75c7d7c139..5d2e13ab58 100644 --- a/common/src/main/java/com/gentics/mesh/router/ProjectsRouterImpl.java +++ b/common/src/main/java/com/gentics/mesh/router/ProjectsRouterImpl.java @@ -36,9 +36,9 @@ public class ProjectsRouterImpl implements ProjectsRouter { private final Vertx vertx; - private APIRouterImpl apiRouter; + private final APIRouterImpl apiRouter; - private Router router; + private final Router router; public ProjectsRouterImpl(Vertx vertx, APIRouterImpl apiRouter) { this.vertx = vertx; @@ -121,4 +121,8 @@ public ProjectRouter projectRouter() { return projectRouter; } + @Override + public Router getRouter() { + return router; + } } diff --git a/common/src/main/java/com/gentics/mesh/router/route/AbstractInternalEndpoint.java b/common/src/main/java/com/gentics/mesh/router/route/AbstractInternalEndpoint.java index 223224662c..8fa06a1937 100644 --- a/common/src/main/java/com/gentics/mesh/router/route/AbstractInternalEndpoint.java +++ b/common/src/main/java/com/gentics/mesh/router/route/AbstractInternalEndpoint.java @@ -141,4 +141,8 @@ protected boolean isOrderedBlockingHandlers() { return Optional.ofNullable(options).map(MeshOptions::getVertxOptions) .map(VertxOptions::isOrderedBlockingHandlers).orElse(true); } + + public MeshOptions getOptions() { + return options; + } } diff --git a/common/src/main/java/com/gentics/mesh/util/MeshOpenAPIv3Generator.java b/common/src/main/java/com/gentics/mesh/util/MeshOpenAPIv3Generator.java new file mode 100644 index 0000000000..0755667fbc --- /dev/null +++ b/common/src/main/java/com/gentics/mesh/util/MeshOpenAPIv3Generator.java @@ -0,0 +1,97 @@ +package com.gentics.mesh.util; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.regex.Pattern; + +import com.gentics.vertx.openapi.OpenAPIv3Generator; +import com.gentics.vertx.openapi.model.ExtendedSecurityScheme; +import com.gentics.vertx.openapi.model.Format; +import com.gentics.vertx.openapi.model.InParameter; +import com.gentics.vertx.openapi.model.OpenAPIGenerationException; + +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.vertx.ext.web.Router; + +/** + * Overridden OpenAPI v3 generator, adding Mesh specific features. + */ +public class MeshOpenAPIv3Generator extends OpenAPIv3Generator { + + protected final ExtendedSecurityScheme securityBearerAuth; + + public MeshOpenAPIv3Generator(String version, List servers, + Optional> maybePathBlacklist, + Optional> maybePathWhitelist) { + this(version, servers, false, maybePathBlacklist, maybePathWhitelist); + } + + public MeshOpenAPIv3Generator(String version, List servers, + boolean secureByDefault, + Optional> maybePathBlacklist, + Optional> maybePathWhitelist) { + super(version, servers, Collections.singletonMap("bearerAuth", new ExtendedSecurityScheme(secureByDefault)), maybePathBlacklist, maybePathWhitelist); + securityBearerAuth = security.get("bearerAuth"); + securityBearerAuth.getScheme().setScheme("bearer"); + securityBearerAuth.getScheme().setType(SecurityScheme.Type.HTTP); + securityBearerAuth.getScheme().setBearerFormat("JWT"); + } + + /** + * Generate the specification using some functional shortcuts. + * + * @param routers + * @param format + * @param pretty + * @param useVersion31 + * @return + * @throws OpenAPIGenerationException + */ + public String generate(Map routers, Format format, boolean pretty, boolean useVersion31) throws OpenAPIGenerationException { + return generate("Gentics Mesh REST API", routers, format, pretty, useVersion31); + } + + /** + * Generate the specification using some functional shortcuts and an API name. + * + * @param routers + * @param format + * @param pretty + * @param useVersion31 + * @return + * @throws OpenAPIGenerationException + */ + public String generate(String name, Map routers, Format format, boolean pretty, boolean useVersion31) throws OpenAPIGenerationException { + return generate(name, routers, format, pretty, useVersion31, + // transform project path item + Optional.of((path, item) -> { + if (path.contains("/{project}/")) { + Parameter projectNameParam = new Parameter().name("project").in(InParameter.PATH.toString()).schema(new Schema().type("string").description("Name of the related project")); + item.readOperations().stream() + .forEach(o -> o.getParameters().stream().filter(p -> "project".equals(p.getName())).findAny() + .ifPresentOrElse(present -> { + // already exists, no action + }, () -> o.addParametersItem(projectNameParam))); + } + return path; + }), + // fill the component model + Optional.empty()); + } + + @SuppressWarnings("rawtypes") + @Override + protected void postProcess(Context context) { + // The JSON schema mapper behaves awfully with the field map, making it unusable. + Schema fieldMapSchema = new Schema<>(); + fieldMapSchema.set$ref("#/components/schemas/AnyJson"); + context.usedComponents.add("AnyJson"); + context.openApi.getComponents().addSchemas("FieldMap", fieldMapSchema); + super.postProcess(context); + } +} diff --git a/core/pom.xml b/core/pom.xml index 1accedbd39..51fdd95dd6 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -192,8 +192,23 @@ com.gentics.mesh mesh-service-aws-s3-storage - + + io.swagger.core.v3 + swagger-core + 2.2.20 + + + org.reflections + reflections + 0.10.2 + + + jakarta.xml.bind + jakarta.xml.bind-api + 4.0.1 + + diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/RolePermissionHandlingEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/RolePermissionHandlingEndpoint.java index 31d8371148..a4d63afed2 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/RolePermissionHandlingEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/RolePermissionHandlingEndpoint.java @@ -6,6 +6,7 @@ import static io.vertx.core.http.HttpMethod.DELETE; import static io.vertx.core.http.HttpMethod.GET; import static io.vertx.core.http.HttpMethod.POST; +import static io.vertx.core.http.HttpMethod.PUT; import com.gentics.mesh.auth.MeshAuthChain; import com.gentics.mesh.context.InternalActionContext; @@ -65,20 +66,37 @@ protected void addRolePermissionHandler(String uuidParameterName, String uuidPar crudHandler.handleGrantPermissions(ac, uuid); }, isOrderedBlockingHandlers()); - InternalEndpointRoute revokePermissionsEndpoint = createRoute(); - revokePermissionsEndpoint.path(path); - revokePermissionsEndpoint.addUriParameter(uuidParameterName, "Uuid of the " + typeDescription, uuidParameterExample); - revokePermissionsEndpoint.method(DELETE); - revokePermissionsEndpoint.description("Revoke permissions on the " + typeDescription + " from multiple roles."); - revokePermissionsEndpoint.consumes(APPLICATION_JSON); - revokePermissionsEndpoint.produces(APPLICATION_JSON); - revokePermissionsEndpoint.exampleRequest(roleExamples.getObjectPermissionRevokeRequest(includePublishPermissions)); - revokePermissionsEndpoint.exampleResponse(OK, roleExamples.getObjectPermissionResponse(includePublishPermissions), "Updated permissions."); - revokePermissionsEndpoint.events(ROLE_PERMISSIONS_CHANGED); - revokePermissionsEndpoint.blockingHandler(rc -> { + InternalEndpointRoute revokePermissionsEndpointStandard = createRoute(); + revokePermissionsEndpointStandard.path(path); + revokePermissionsEndpointStandard.addUriParameter(uuidParameterName, "Uuid of the " + typeDescription, uuidParameterExample); + revokePermissionsEndpointStandard.method(PUT); + revokePermissionsEndpointStandard.description("Revoke permissions on the " + typeDescription + " from multiple roles."); + revokePermissionsEndpointStandard.consumes(APPLICATION_JSON); + revokePermissionsEndpointStandard.produces(APPLICATION_JSON); + revokePermissionsEndpointStandard.exampleRequest(roleExamples.getObjectPermissionRevokeRequest(includePublishPermissions)); + revokePermissionsEndpointStandard.exampleResponse(OK, roleExamples.getObjectPermissionResponse(includePublishPermissions), "Updated permissions."); + revokePermissionsEndpointStandard.events(ROLE_PERMISSIONS_CHANGED); + revokePermissionsEndpointStandard.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); String uuid = rc.request().getParam(uuidParameterName); crudHandler.handleRevokePermissions(ac, uuid); }, isOrderedBlockingHandlers()); + + InternalEndpointRoute revokePermissionsEndpointNonStandard = createRoute(); + revokePermissionsEndpointNonStandard.path(path); + revokePermissionsEndpointNonStandard.addUriParameter(uuidParameterName, "Uuid of the " + typeDescription, uuidParameterExample); + revokePermissionsEndpointNonStandard.method(DELETE); + revokePermissionsEndpointNonStandard.description("Revoke permissions on the " + typeDescription + " from multiple roles."); + revokePermissionsEndpointNonStandard.consumes(APPLICATION_JSON); + revokePermissionsEndpointNonStandard.produces(APPLICATION_JSON); + revokePermissionsEndpointNonStandard.exampleRequest(roleExamples.getObjectPermissionRevokeRequest(includePublishPermissions)); + revokePermissionsEndpointNonStandard.exampleResponse(OK, roleExamples.getObjectPermissionResponse(includePublishPermissions), "Updated permissions."); + revokePermissionsEndpointNonStandard.events(ROLE_PERMISSIONS_CHANGED); + revokePermissionsEndpointNonStandard.setHidden(true); + revokePermissionsEndpointNonStandard.blockingHandler(rc -> { + InternalActionContext ac = wrap(rc); + String uuid = rc.request().getParam(uuidParameterName); + crudHandler.handleRevokePermissions(ac, uuid); + }, isOrderedBlockingHandlers()); } } diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/RolePermissionHandlingProjectEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/RolePermissionHandlingProjectEndpoint.java index 7f0205317c..4ba89bc66f 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/RolePermissionHandlingProjectEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/RolePermissionHandlingProjectEndpoint.java @@ -6,6 +6,7 @@ import static io.vertx.core.http.HttpMethod.DELETE; import static io.vertx.core.http.HttpMethod.GET; import static io.vertx.core.http.HttpMethod.POST; +import static io.vertx.core.http.HttpMethod.PUT; import com.gentics.mesh.auth.MeshAuthChain; import com.gentics.mesh.cli.BootstrapInitializer; @@ -67,17 +68,34 @@ protected void addRolePermissionHandler(String uuidParameterName, String uuidPar crudHandler.handleGrantPermissions(ac, uuid); }, isOrderedBlockingHandlers()); - InternalEndpointRoute revokePermissionsEndpoint = createRoute(); - revokePermissionsEndpoint.path(path); - revokePermissionsEndpoint.addUriParameter(uuidParameterName, "Uuid of the " + typeDescription, uuidParameterExample); - revokePermissionsEndpoint.method(DELETE); - revokePermissionsEndpoint.description("Revoke permissions on the " + typeDescription + " from multiple roles."); - revokePermissionsEndpoint.consumes(APPLICATION_JSON); - revokePermissionsEndpoint.produces(APPLICATION_JSON); - revokePermissionsEndpoint.exampleRequest(roleExamples.getObjectPermissionRevokeRequest(includePublishPermissions)); - revokePermissionsEndpoint.exampleResponse(OK, roleExamples.getObjectPermissionResponse(includePublishPermissions), "Updated permissions."); - revokePermissionsEndpoint.events(ROLE_PERMISSIONS_CHANGED); - revokePermissionsEndpoint.blockingHandler(rc -> { + InternalEndpointRoute revokePermissionsEndpointNonStandard = createRoute(); + revokePermissionsEndpointNonStandard.path(path); + revokePermissionsEndpointNonStandard.addUriParameter(uuidParameterName, "Uuid of the " + typeDescription, uuidParameterExample); + revokePermissionsEndpointNonStandard.method(DELETE); + revokePermissionsEndpointNonStandard.setHidden(true); + revokePermissionsEndpointNonStandard.description("Revoke permissions on the " + typeDescription + " from multiple roles."); + revokePermissionsEndpointNonStandard.consumes(APPLICATION_JSON); + revokePermissionsEndpointNonStandard.produces(APPLICATION_JSON); + revokePermissionsEndpointNonStandard.exampleRequest(roleExamples.getObjectPermissionRevokeRequest(includePublishPermissions)); + revokePermissionsEndpointNonStandard.exampleResponse(OK, roleExamples.getObjectPermissionResponse(includePublishPermissions), "Updated permissions."); + revokePermissionsEndpointNonStandard.events(ROLE_PERMISSIONS_CHANGED); + revokePermissionsEndpointNonStandard.blockingHandler(rc -> { + InternalActionContext ac = wrap(rc); + String uuid = rc.request().getParam(uuidParameterName); + crudHandler.handleRevokePermissions(ac, uuid); + }, isOrderedBlockingHandlers()); + + InternalEndpointRoute revokePermissionsEndpointStandard = createRoute(); + revokePermissionsEndpointStandard.path(path); + revokePermissionsEndpointStandard.addUriParameter(uuidParameterName, "Uuid of the " + typeDescription, uuidParameterExample); + revokePermissionsEndpointStandard.method(PUT); + revokePermissionsEndpointStandard.description("Revoke permissions on the " + typeDescription + " from multiple roles."); + revokePermissionsEndpointStandard.consumes(APPLICATION_JSON); + revokePermissionsEndpointStandard.produces(APPLICATION_JSON); + revokePermissionsEndpointStandard.exampleRequest(roleExamples.getObjectPermissionRevokeRequest(includePublishPermissions)); + revokePermissionsEndpointStandard.exampleResponse(OK, roleExamples.getObjectPermissionResponse(includePublishPermissions), "Updated permissions."); + revokePermissionsEndpointStandard.events(ROLE_PERMISSIONS_CHANGED); + revokePermissionsEndpointStandard.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); String uuid = rc.request().getParam(uuidParameterName); crudHandler.handleRevokePermissions(ac, uuid); diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/admin/AdminEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/admin/AdminEndpoint.java index a6abb4cacb..db7578fb1f 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/admin/AdminEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/admin/AdminEndpoint.java @@ -9,6 +9,7 @@ import static com.gentics.mesh.example.ExampleUuids.JOB_UUID; import static com.gentics.mesh.example.ExampleUuids.PLUGIN_1_ID; import static com.gentics.mesh.http.HttpConstants.APPLICATION_JSON; +import static io.netty.handler.codec.http.HttpResponseStatus.NO_CONTENT; import static io.netty.handler.codec.http.HttpResponseStatus.OK; import static io.vertx.core.http.HttpMethod.DELETE; import static io.vertx.core.http.HttpMethod.GET; @@ -28,6 +29,7 @@ import com.gentics.mesh.etc.config.MeshOptions; import com.gentics.mesh.parameter.impl.ConsistencyCheckParametersImpl; import com.gentics.mesh.parameter.impl.JobParametersImpl; +import com.gentics.mesh.parameter.impl.PagingParametersImpl; import com.gentics.mesh.rest.InternalEndpointRoute; import com.gentics.mesh.router.route.AbstractInternalEndpoint; @@ -138,16 +140,16 @@ protected void addPluginHandler() { }, isOrderedBlockingHandlers()); InternalEndpointRoute readEndpoint = createRoute(); - readEndpoint.path("/plugins/:uuid"); + readEndpoint.path("/plugins/:id"); readEndpoint.method(GET); readEndpoint.description("Loads deployment information for the plugin with the given id."); readEndpoint.produces(APPLICATION_JSON); - readEndpoint.addUriParameter("uuid", "Uuid of the plugin.", PLUGIN_1_ID); + readEndpoint.addUriParameter("id", "Id of the plugin.", PLUGIN_1_ID); readEndpoint.exampleResponse(OK, adminExamples.createHelloWorldPluginResponse(), "Plugin response."); readEndpoint.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); - String uuid = ac.getParameter("uuid"); - pluginHandler.handleRead(ac, uuid); + String id = ac.getParameter("id"); + pluginHandler.handleRead(ac, id); }, false); InternalEndpointRoute readAllEndpoint = createRoute(); @@ -156,6 +158,7 @@ protected void addPluginHandler() { readAllEndpoint.description("Loads deployment information for all deployed plugins."); readAllEndpoint.produces(APPLICATION_JSON); readAllEndpoint.exampleResponse(OK, adminExamples.createPluginListResponse(), "Plugin list response."); + readAllEndpoint.addQueryParameters(PagingParametersImpl.class); readAllEndpoint.blockingHandler(rc -> { pluginHandler.handleReadList(wrap(rc)); }, false); @@ -271,6 +274,7 @@ protected void addJobHandler() { deleteJob.method(DELETE); deleteJob.description("Deletes the job. Note that it is only possible to delete failed jobs"); deleteJob.addUriParameter("jobUuid", "Uuid of the job.", JOB_UUID); + deleteJob.exampleResponse(NO_CONTENT, "Job has been deleted."); deleteJob.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); String uuid = ac.getParameter("jobUuid"); @@ -281,6 +285,7 @@ protected void addJobHandler() { processJob.path("/jobs/:jobUuid/process"); processJob.method(POST); processJob.description("Process the job. Failed jobs will be automatically reset and put in queued state."); + processJob.exampleResponse(OK, jobExamples.createJobResponse(), "Job information."); processJob.addUriParameter("jobUuid", "Uuid of the job.", JOB_UUID); processJob.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); @@ -292,6 +297,7 @@ protected void addJobHandler() { resetJob.path("/jobs/:jobUuid/error"); resetJob.method(DELETE); resetJob.description("Deletes error state from the job. This will make it possible to execute the job once again."); + resetJob.exampleResponse(NO_CONTENT, "Job has been reset."); resetJob.addUriParameter("jobUuid", "Uuid of the job.", JOB_UUID); resetJob.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); @@ -304,6 +310,8 @@ protected void addDebugInfoHandler() { InternalEndpointRoute route = createRoute(); route.path("/debuginfo"); route.method(GET); + route.produces("*/*"); + route.exampleResponse(OK, "ZIP file"); route.description("Downloads a zip file of various [debug information](/docs/administration-guide/#debuginfo) files."); route.addQueryParameter("include", "Information to include. See the [documentation](/docs/administration-guide/#debuginfo) for possible usages.", "-log,consistencyCheck"); route.handler(rc -> debugInfoHandler.handle(rc)); @@ -323,6 +331,8 @@ protected void addRuntimeConfigHandler() { postRoute.method(POST); postRoute.setMutating(false); postRoute.produces(APPLICATION_JSON); + postRoute.consumes(APPLICATION_JSON); + postRoute.exampleRequest(localConfig.createExample()); postRoute.description("Sets the currently active local configuration of this instance."); postRoute.exampleResponse(OK, localConfig.createExample(), "The currently active local configuration"); postRoute.handler(rc -> localConfigHandler.handleSetActiveConfig(wrap(rc))); diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/admin/AdminHandler.java b/core/src/main/java/com/gentics/mesh/core/endpoint/admin/AdminHandler.java index 04eb2b45c7..eaf0d1da2a 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/admin/AdminHandler.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/admin/AdminHandler.java @@ -32,7 +32,9 @@ import com.gentics.mesh.core.verticle.handler.WriteLock; import com.gentics.mesh.distributed.coordinator.Coordinator; import com.gentics.mesh.distributed.coordinator.MasterServer; +import com.gentics.mesh.etc.config.Format; import com.gentics.mesh.etc.config.MeshOptions; +import com.gentics.mesh.etc.config.Version; import com.gentics.mesh.generator.RAMLGenerator; import com.gentics.mesh.parameter.BackupParameters; import com.gentics.mesh.router.RouterStorageImpl; @@ -226,6 +228,22 @@ public MeshServerInfoModel getMeshServerInfoModel(InternalActionContext ac) { return info; } + /** + * Handle a request of generating OpenAPI spec for all the routes. All the necessary parameters will be taken from an action context. + * + * @param ac internal action context. + */ + public void handleOpenAPIv3(InternalActionContext ac) { + handleOpenAPIv3(ac, options.getDefaultOpenAPIFormat(), options.getDefaultOpenAPIVersion()); + } + + /** + * Handle a request of generating OpenAPI spec for all the routes, using the configured format and version. + * + * @param ac internal action context. + */ + public abstract void handleOpenAPIv3(InternalActionContext ac, Format format, Version version); + /** * Generate and return the RAML of the server. * diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/admin/HealthEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/admin/HealthEndpoint.java index a533ec4311..4319d7d6f4 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/admin/HealthEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/admin/HealthEndpoint.java @@ -11,6 +11,8 @@ import com.gentics.mesh.rest.InternalEndpointRoute; import com.gentics.mesh.router.route.AbstractInternalEndpoint; +import io.netty.handler.codec.http.HttpResponseStatus; + /** * Endpoint definition for health / readiness checks */ @@ -42,25 +44,31 @@ public String getDescription() { private void addLive() { InternalEndpointRoute deployEndpoint = createRoute(); + deployEndpoint.setInsecure(true); deployEndpoint.path("/live"); deployEndpoint.method(GET); deployEndpoint.description("Returns an empty response with status code 200 if Gentics Mesh is alive."); + deployEndpoint.exampleResponse(HttpResponseStatus.OK, "Mesh is alive."); deployEndpoint.handler(rc -> monitoringCrudHandler.handleLive(rc)); } private void addReady() { InternalEndpointRoute deployEndpoint = createRoute(); deployEndpoint.path("/ready"); + deployEndpoint.setInsecure(true); deployEndpoint.method(GET); deployEndpoint.description("Returns an empty response with status code 200 if Gentics Mesh is ready. Responds with 503 otherwise."); + deployEndpoint.exampleResponse(HttpResponseStatus.OK, "Mesh is ready."); deployEndpoint.handler(rc -> monitoringCrudHandler.handleReady(rc)); } private void addWritable() { InternalEndpointRoute deployEndpoint = createRoute(); deployEndpoint.path("/writable"); + deployEndpoint.setInsecure(true); deployEndpoint.method(GET); deployEndpoint.description("Returns an empty response with status code 200 if Gentics Mesh is writable. Responds with 503 otherwise."); + deployEndpoint.exampleResponse(HttpResponseStatus.OK, "Mesh is writable."); deployEndpoint.handler(rc -> monitoringCrudHandler.handleWritable(rc)); } } diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/admin/RestInfoEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/admin/RestInfoEndpoint.java index b43b39984f..233abd9a9a 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/admin/RestInfoEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/admin/RestInfoEndpoint.java @@ -5,17 +5,17 @@ import static io.netty.handler.codec.http.HttpResponseStatus.OK; import static io.vertx.core.http.HttpMethod.GET; -import javax.inject.Inject; - import com.gentics.mesh.auth.MeshAuthChain; import com.gentics.mesh.context.InternalActionContext; import com.gentics.mesh.core.db.Database; +import com.gentics.mesh.etc.config.Format; import com.gentics.mesh.etc.config.MeshOptions; import com.gentics.mesh.example.RestInfoExamples; import com.gentics.mesh.rest.InternalEndpointRoute; import com.gentics.mesh.router.RouterStorage; import com.gentics.mesh.router.route.AbstractInternalEndpoint; +import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.Vertx; import io.vertx.ext.web.Router; @@ -24,13 +24,12 @@ */ public class RestInfoEndpoint extends AbstractInternalEndpoint { - private RestInfoExamples examples = new RestInfoExamples(); + protected RestInfoExamples examples = new RestInfoExamples(); - private AdminHandler adminHandler; + protected AdminHandler adminHandler; - private RouterStorage routerStorage; + protected RouterStorage routerStorage; - @Inject public RestInfoEndpoint(MeshAuthChain chain, AdminHandler adminHandler, LocalConfigApi localConfigApi, Database db, MeshOptions options) { super(null, chain, localConfigApi, db, options); this.adminHandler = adminHandler; @@ -67,8 +66,27 @@ public void registerEndPoints() { adminHandler.handleRAML(ac); }, false); + MeshOptions options = getOptions(); + secure("/openapi." + options.getDefaultOpenAPIFormat().name().toLowerCase()); + InternalEndpointRoute openapiYml = createRoute(); + openapiYml.path("/openapi." + options.getDefaultOpenAPIFormat().name().toLowerCase()); + openapiYml.method(GET); + openapiYml.description("Endpoint which provides an OpenAPI v" + options.getDefaultOpenAPIVersion().pretty() + " " + options.getDefaultOpenAPIFormat().name() + " document for all registed endpoints."); + openapiYml.displayName("OpenAPI specification"); + openapiYml.exampleResponse(OK, "Not yet specified"); + openapiYml.produces(options.getDefaultOpenAPIFormat() == Format.JSON ? APPLICATION_JSON : APPLICATION_YAML); + openapiYml.blockingHandler(rc -> { + InternalActionContext ac = wrap(rc); + if (getOptions().isServeOpenApi()) { + adminHandler.handleOpenAPIv3(ac); + } else { + ac.send(HttpResponseStatus.FORBIDDEN); + } + }, false); + secure("/"); InternalEndpointRoute infoEndpoint = createRoute(); + infoEndpoint.setInsecure(true); infoEndpoint.path("/"); infoEndpoint.description("Endpoint which returns version information"); infoEndpoint.displayName("Version Information"); diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/auth/AuthenticationEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/auth/AuthenticationEndpoint.java index 79c95fa16b..ecdd6a66e9 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/auth/AuthenticationEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/auth/AuthenticationEndpoint.java @@ -71,6 +71,7 @@ public void registerEndPoints() { loginEndpoint.path("/login"); loginEndpoint.method(POST); loginEndpoint.setMutating(false); + loginEndpoint.setInsecure(true); loginEndpoint.consumes(APPLICATION_JSON); loginEndpoint.produces(APPLICATION_JSON); loginEndpoint.description("Login via this dedicated login endpoint."); diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/branch/BranchEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/branch/BranchEndpoint.java index ad32b10715..2532d7d6f9 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/branch/BranchEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/branch/BranchEndpoint.java @@ -247,8 +247,8 @@ private void addUpdateHandler() { updateBranch.consumes(APPLICATION_JSON); updateBranch.produces(APPLICATION_JSON); updateBranch.exampleRequest(versioningExamples.createBranchUpdateRequest("Winter Collection Branch")); - updateBranch.exampleResponse(OK, versioningExamples.createBranchResponse("Winter Collection Branch", false), "Updated branch"); - updateBranch.events(BRANCH_UPDATED); + updateBranch.exampleResponse(OK, versioningExamples.createBranchResponse("Winter Collection Branch", false), "Updated or new branch"); + updateBranch.events(BRANCH_CREATED, BRANCH_UPDATED); updateBranch.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); String uuid = rc.request().params().get("branchUuid"); diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/eventbus/EventbusEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/eventbus/EventbusEndpoint.java index 96c357303b..95ac0a36de 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/eventbus/EventbusEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/eventbus/EventbusEndpoint.java @@ -55,9 +55,10 @@ private void addEventBusHandler() { secureAll(); InternalEndpointRoute endpoint = createRoute(); endpoint.setRAMLPath("/"); + endpoint.setHidden(true); endpoint.description("This endpoint provides a sockjs compliant websocket which can be used to interface with the vert.x eventbus."); - if (!isRamlGeneratorContext()) { + if (!isSpecGeneratorContext()) { SockJSHandlerOptions sockJSoptions = new SockJSHandlerOptions().setHeartbeatInterval(2000); SockJSHandler handler = SockJSHandler.create(vertx, sockJSoptions); SockJSBridgeOptions bridgeOptions = new SockJSBridgeOptions(); @@ -91,10 +92,10 @@ private void addEventBusHandler() { } /** - * Returns whether the method is called from during the documentation generation context. + * Returns whether the method is called from during the specification generation context. * @return */ - private boolean isRamlGeneratorContext() { + private boolean isSpecGeneratorContext() { return localRouter == null; } } diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/group/GroupEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/group/GroupEndpoint.java index 95dff5296c..596c115872 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/group/GroupEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/group/GroupEndpoint.java @@ -191,14 +191,13 @@ private void addUpdateHandler() { endpoint.consumes(APPLICATION_JSON); endpoint.produces(APPLICATION_JSON); endpoint.exampleRequest(groupExamples.getGroupUpdateRequest("New group name")); - endpoint.exampleResponse(OK, groupExamples.getGroupResponse1("New group name"), "Updated group."); - endpoint.events(GROUP_UPDATED); + endpoint.exampleResponse(OK, groupExamples.getGroupResponse1("New group name"), "Updated or new group."); + endpoint.events(GROUP_CREATED, GROUP_UPDATED); endpoint.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); String uuid = ac.getParameter("groupUuid"); crudHandler.handleUpdate(ac, uuid); }, isOrderedBlockingHandlers()); - } private void addReadHandler() { diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/microschema/MicroschemaEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/microschema/MicroschemaEndpoint.java index 7120c2efa7..6851bc67e5 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/microschema/MicroschemaEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/microschema/MicroschemaEndpoint.java @@ -171,8 +171,8 @@ private void addUpdateHandler() { endpoint.exampleRequest(microschemaExamples.getGeolocationMicroschemaUpdateRequest()); // endpoint.exampleResponse(OK, microschemaExamples.getGeolocationMicroschemaResponse(), "Updated microschema."); endpoint.exampleResponse(OK, miscExamples.createMessageResponse(), "Migration message."); - endpoint.description("Update the microschema with the given uuid."); - endpoint.events(MICROSCHEMA_UPDATED, MICROSCHEMA_MIGRATION_START, MICROSCHEMA_MIGRATION_FINISHED); + endpoint.description("Update or create the microschema with the given uuid."); + endpoint.events(MICROSCHEMA_UPDATED, MICROSCHEMA_CREATED, MICROSCHEMA_MIGRATION_START, MICROSCHEMA_MIGRATION_FINISHED); endpoint.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); String uuid = ac.getParameter("microschemaUuid"); diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/microschema/ProjectMicroschemaEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/microschema/ProjectMicroschemaEndpoint.java index 8cc0e1824a..47e90e2bda 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/microschema/ProjectMicroschemaEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/microschema/ProjectMicroschemaEndpoint.java @@ -18,6 +18,8 @@ import com.gentics.mesh.core.db.Database; import com.gentics.mesh.core.endpoint.admin.LocalConfigApi; import com.gentics.mesh.etc.config.MeshOptions; +import com.gentics.mesh.parameter.impl.GenericParametersImpl; +import com.gentics.mesh.parameter.impl.PagingParametersImpl; import com.gentics.mesh.rest.InternalEndpointRoute; import com.gentics.mesh.router.route.AbstractProjectEndpoint; @@ -56,6 +58,8 @@ private void addReadHandlers() { endpoint.path("/"); endpoint.method(GET); endpoint.produces(APPLICATION_JSON); + endpoint.addQueryParameters(PagingParametersImpl.class); + endpoint.addQueryParameters(GenericParametersImpl.class); endpoint.description("Read all microschemas which are assigned to the project."); endpoint.exampleResponse(OK, microschemaExamples.getMicroschemaListResponse(), "List of assigned microschemas."); endpoint.handler(rc -> { diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/node/AbstractBinaryUploadHandler.java b/core/src/main/java/com/gentics/mesh/core/endpoint/node/AbstractBinaryUploadHandler.java index 0d36e78e0a..3bae414dd2 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/node/AbstractBinaryUploadHandler.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/node/AbstractBinaryUploadHandler.java @@ -7,6 +7,9 @@ import static io.netty.handler.codec.http.HttpResponseStatus.OK; import static org.apache.commons.lang3.StringUtils.isEmpty; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.gentics.mesh.context.InternalActionContext; import com.gentics.mesh.core.data.HibLanguage; import com.gentics.mesh.core.data.HibNodeFieldContainer; @@ -28,8 +31,6 @@ import com.gentics.mesh.etc.config.MeshOptions; import io.reactivex.Flowable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Base class for binary upload handler and S3 binary upload handler. @@ -63,19 +64,19 @@ public void handleBinaryCheckResult(InternalActionContext ac, String nodeUuid, S validateParameter(nodeUuid, "uuid"); validateParameter(fieldName, "fieldName"); - String languageTag = ac.getParameter("lang"); + String[] languageTag = ac.getLanguageParameters().getLanguages(); - if (isEmpty(languageTag)) { + if (languageTag == null || languageTag.length < 1) { throw error(BAD_REQUEST, "upload_error_no_language"); } - String nodeVersion = ac.getParameter("version"); + String nodeVersion = ac.getVersioningParameters().getVersion(); if (isEmpty(nodeVersion)) { throw error(BAD_REQUEST, "upload_error_no_version"); } - String checkSecret = ac.getParameter("secret"); + String checkSecret = ac.getBinaryCheckParameters().getSecret(); if (isEmpty(checkSecret)) { throw error(BAD_REQUEST, "error_binaryfield_invalid_check_secret", fieldName); @@ -85,7 +86,7 @@ public void handleBinaryCheckResult(InternalActionContext ac, String nodeUuid, S (batch, tx) -> { CommonTx ctx = tx.unwrap(); HibProject project = tx.getProject(ac); - HibLanguage language = tx.languageDao().findByLanguageTag(project, languageTag); + HibLanguage language = tx.languageDao().findByLanguageTag(project, languageTag[0]); if (language == null) { throw error(NOT_FOUND, "error_language_not_found", languageTag); @@ -94,7 +95,7 @@ public void handleBinaryCheckResult(InternalActionContext ac, String nodeUuid, S HibBranch branch = tx.getBranch(ac); NodeDao nodeDao = tx.nodeDao(); HibNode node = nodeDao.loadObjectByUuid(project, ac, nodeUuid, UPDATE_PERM); - HibNodeFieldContainer nodeFieldContainer = ctx.contentDao().findVersion(node, languageTag, branch.getUuid(), nodeVersion); + HibNodeFieldContainer nodeFieldContainer = ctx.contentDao().findVersion(node, languageTag[0], branch.getUuid(), nodeVersion); if (nodeFieldContainer == null) { throw error(BAD_REQUEST, "object_not_found_for_uuid_version", nodeUuid, nodeVersion); diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/node/NodeEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/node/NodeEndpoint.java index 2759091699..5557bda3bb 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/node/NodeEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/node/NodeEndpoint.java @@ -16,7 +16,6 @@ import static com.gentics.mesh.example.ExampleUuids.TAG_RED_UUID; import static com.gentics.mesh.example.ExampleUuids.UUID_1; import static com.gentics.mesh.http.HttpConstants.APPLICATION_JSON; -import static com.gentics.mesh.http.HttpConstants.APPLICATION_OCTET_STREAM; import static com.gentics.mesh.http.HttpConstants.MULTIPART_FORM_DATA; import static io.netty.handler.codec.http.HttpResponseStatus.CONFLICT; import static io.netty.handler.codec.http.HttpResponseStatus.CREATED; @@ -30,7 +29,9 @@ import javax.inject.Inject; import org.apache.commons.lang3.StringUtils; +import org.raml.model.ParamType; import org.raml.model.Resource; +import org.raml.model.parameter.QueryParameter; import com.gentics.mesh.auth.MeshAuthChain; import com.gentics.mesh.cli.BootstrapInitializer; @@ -40,6 +41,7 @@ import com.gentics.mesh.core.endpoint.admin.LocalConfigApi; import com.gentics.mesh.core.rest.navigation.NavigationResponse; import com.gentics.mesh.etc.config.MeshOptions; +import com.gentics.mesh.parameter.impl.BinaryCheckParametersImpl; import com.gentics.mesh.parameter.impl.BranchParametersImpl; import com.gentics.mesh.parameter.impl.DeleteParametersImpl; import com.gentics.mesh.parameter.impl.GenericParametersImpl; @@ -176,6 +178,8 @@ private void addLanguageHandlers() { endpoint.addUriParameter("language", "Language tag of the content which should be deleted.", "en"); endpoint.method(DELETE); endpoint.produces(APPLICATION_JSON); + endpoint.addQueryParameters(DeleteParametersImpl.class); + endpoint.addQueryParameters(BranchParametersImpl.class); endpoint.description("Delete the language specific content of the node."); endpoint.exampleResponse(NO_CONTENT, "Language variation of the node has been deleted."); endpoint.exampleResponse(NOT_FOUND, miscExamples.createMessageResponse(), "The node could not be found."); @@ -189,11 +193,16 @@ private void addLanguageHandlers() { } private void addBinaryHandlers() { + QueryParameter publishQueryParameter = new QueryParameter(); + publishQueryParameter.setDescription("Should the saved data be published at once"); + publishQueryParameter.setDefaultValue("false"); + publishQueryParameter.setType(ParamType.BOOLEAN); + InternalEndpointRoute fieldUpdate = createRoute(); fieldUpdate.path("/:nodeUuid/binary/:fieldName"); fieldUpdate.addUriParameter("nodeUuid", "Uuid of the node.", NODE_DELOREAN_UUID); fieldUpdate.addUriParameter("fieldName", "Name of the field which should be created.", "stringField"); - fieldUpdate.addUriParameter("publish", "Whether the node shall be published after updating the binary field", "true"); + fieldUpdate.addQueryParameter("publish", publishQueryParameter); fieldUpdate.method(POST); fieldUpdate.consumes(MULTIPART_FORM_DATA); fieldUpdate.produces(APPLICATION_JSON); @@ -210,10 +219,17 @@ private void addBinaryHandlers() { binaryUploadHandler.handleUpdateField(ac, uuid, fieldName, attributes); }, isOrderedBlockingHandlers()); + QueryParameter lang = new QueryParameter(); + lang.setExample("en"); + lang.setRequired(true); + lang.setDescription("Node language"); InternalEndpointRoute checkCallback = createRoute(); checkCallback.path("/:nodeUuid/binary/:fieldName/checkCallback"); checkCallback.addUriParameter("nodeUuid", "Uuid of the node.", NODE_DELOREAN_UUID); checkCallback.addUriParameter("fieldName", "Name of the field for which the check status is to be updated.", "stringField"); + checkCallback.addQueryParameters(VersioningParametersImpl.class); + checkCallback.addQueryParameter("lang", lang); + checkCallback.addQueryParameters(BinaryCheckParametersImpl.class); checkCallback.method(POST); checkCallback.produces(APPLICATION_JSON); checkCallback.exampleRequest(nodeExamples.getExampleBinaryCheckCallbackParameters()); @@ -253,6 +269,7 @@ private void addBinaryHandlers() { fieldGet.addQueryParameters(ImageManipulationParametersImpl.class); fieldGet.addQueryParameters(VersioningParametersImpl.class); fieldGet.method(GET); + fieldGet.produces("*/*"); fieldGet.description( "Download the binary field with the given name. You can use image query parameters for crop and resize if the binary data represents an image."); fieldGet.blockingHandler(rc -> { @@ -325,7 +342,7 @@ private void addS3BinaryHandlers() { fieldUpdate.addQueryParameters(VersioningParametersImpl.class); fieldUpdate.method(POST); fieldUpdate.produces(APPLICATION_JSON); - fieldUpdate.exampleRequest(nodeExamples.getExampleBinaryUploadFormParameters()); + fieldUpdate.exampleRequest(nodeExamples.getExampleS3BinaryUploadFormParameters()); fieldUpdate.exampleResponse(OK, nodeExamples.getNodeResponseWithAllFields(), "The response contains the updated node."); fieldUpdate.exampleResponse(NOT_FOUND, miscExamples.createMessageResponse(), "The node or the field could not be found."); fieldUpdate.description("Create the s3 binaryfield with the given name."); @@ -363,7 +380,7 @@ private void addS3BinaryHandlers() { fieldMetadataExtraction.addQueryParameters(VersioningParametersImpl.class); fieldMetadataExtraction.method(POST); fieldMetadataExtraction.produces(APPLICATION_JSON); - fieldMetadataExtraction.exampleRequest(nodeExamples.getExampleBinaryUploadFormParameters()); + fieldMetadataExtraction.exampleRequest(nodeExamples.getExampleS3BinaryUploadFormParameters()); fieldMetadataExtraction.exampleResponse(OK, nodeExamples.getNodeResponseWithAllFields(), "The response contains the updated node."); fieldMetadataExtraction.exampleResponse(NOT_FOUND, miscExamples.createMessageResponse(), "The node or the field could not be found."); fieldMetadataExtraction.description("Parse metadata of s3 binaryfield with the given name."); @@ -578,10 +595,9 @@ private void addUpdateHandler() { endpoint.method(POST); endpoint.consumes(APPLICATION_JSON); endpoint.produces(APPLICATION_JSON); - endpoint.exampleRequest(nodeExamples.getNodeUpdateRequest()); - endpoint.exampleResponse(OK, nodeExamples.getNodeResponse2(), "Updated node."); + endpoint.exampleRequest(nodeExamples.getNodeUpdateRequest2()); + endpoint.exampleResponse(OK, nodeExamples.getNodeResponse2(), "New or updated node."); endpoint.exampleResponse(CONFLICT, miscExamples.createMessageResponse(), "A conflict has been detected."); - endpoint.exampleResponse(NOT_FOUND, miscExamples.createMessageResponse(), "The node could not be found."); endpoint.events(NODE_UPDATED, NODE_CREATED, NODE_CONTENT_CREATED, NODE_UPDATED); endpoint.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/project/LanguageEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/project/LanguageEndpoint.java index 1fc220464f..851b67ede2 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/project/LanguageEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/project/LanguageEndpoint.java @@ -25,6 +25,11 @@ public class LanguageEndpoint extends AbstractInternalEndpoint { private final LanguageCrudHandler crudHandler; + public LanguageEndpoint() { + super("languages", null, null, null, null); + this.crudHandler = null; + } + @Inject public LanguageEndpoint(MeshAuthChain chain, LocalConfigApi localConfigApi, Database db, MeshOptions options, LanguageCrudHandler crudHandler) { super("languages", chain, localConfigApi, db, options); diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/role/RoleEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/role/RoleEndpoint.java index b1b1e06a11..f5fac3e1cc 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/role/RoleEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/role/RoleEndpoint.java @@ -124,7 +124,7 @@ private void addUpdateHandler() { endpoint.method(POST); endpoint.consumes(APPLICATION_JSON); endpoint.exampleRequest(roleExamples.getRoleUpdateRequest("New role name")); - endpoint.exampleResponse(OK, roleExamples.getRoleResponse1("New role name"), "Updated role."); + endpoint.exampleResponse(OK, roleExamples.getRoleResponse1("New role name"), "Updated or new role."); endpoint.events(ROLE_UPDATED, ROLE_CREATED); endpoint.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/schema/ProjectSchemaEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/schema/ProjectSchemaEndpoint.java index 72906b4f05..9343e5a8ea 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/schema/ProjectSchemaEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/schema/ProjectSchemaEndpoint.java @@ -20,6 +20,8 @@ import com.gentics.mesh.core.db.Database; import com.gentics.mesh.core.endpoint.admin.LocalConfigApi; import com.gentics.mesh.etc.config.MeshOptions; +import com.gentics.mesh.parameter.impl.GenericParametersImpl; +import com.gentics.mesh.parameter.impl.PagingParametersImpl; import com.gentics.mesh.rest.InternalEndpointRoute; import com.gentics.mesh.router.route.AbstractProjectEndpoint; @@ -75,6 +77,8 @@ private void addReadHandlers() { readAll.path("/"); readAll.method(GET); readAll.description("Read multiple schemas and return a paged list response."); + readAll.addQueryParameters(PagingParametersImpl.class); + readAll.addQueryParameters(GenericParametersImpl.class); readAll.exampleResponse(OK, schemaExamples.getSchemaListResponse(), "Loaded list of schemas."); readAll.produces(APPLICATION_JSON); readAll.blockingHandler(rc -> { diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/schema/SchemaEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/schema/SchemaEndpoint.java index 0a51b7c0b9..8f0322f895 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/schema/SchemaEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/schema/SchemaEndpoint.java @@ -137,13 +137,14 @@ private void addUpdateHandler() { endpoint.path("/:schemaUuid"); endpoint.addUriParameter("schemaUuid", "Uuid of the schema.", SCHEMA_VEHICLE_UUID); endpoint.method(POST); - endpoint.description("Update the schema."); + endpoint.description("Update or create the schema."); endpoint.consumes(APPLICATION_JSON); endpoint.produces(APPLICATION_JSON); + endpoint.addQueryParameters(SchemaUpdateParametersImpl.class); endpoint.exampleRequest(schemaExamples.getSchemaUpdateRequest()); - endpoint.exampleResponse(OK, schemaExamples.getSchemaResponse(), "Updated schema."); - endpoint.events(SCHEMA_UPDATED, SCHEMA_MIGRATION_START, SCHEMA_MIGRATION_FINISHED); + endpoint.exampleResponse(OK, schemaExamples.getSchemaResponse(), "Updated or new schema."); + endpoint.events(SCHEMA_CREATED, SCHEMA_UPDATED, SCHEMA_MIGRATION_START, SCHEMA_MIGRATION_FINISHED); endpoint.blockingHandler(rc -> { // Update operations should always be executed sequentially - never in parallel synchronized (schemaLock.mutex()) { diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/tagfamily/TagFamilyEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/tagfamily/TagFamilyEndpoint.java index 6fc007d909..2e9b1679f7 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/tagfamily/TagFamilyEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/tagfamily/TagFamilyEndpoint.java @@ -17,6 +17,7 @@ import static io.vertx.core.http.HttpMethod.DELETE; import static io.vertx.core.http.HttpMethod.GET; import static io.vertx.core.http.HttpMethod.POST; +import static io.vertx.core.http.HttpMethod.PUT; import javax.inject.Inject; @@ -33,6 +34,7 @@ import com.gentics.mesh.core.endpoint.tag.TagCrudHandler; import com.gentics.mesh.etc.config.MeshOptions; import com.gentics.mesh.parameter.impl.BranchParametersImpl; +import com.gentics.mesh.parameter.impl.EtagParametersImpl; import com.gentics.mesh.parameter.impl.GenericParametersImpl; import com.gentics.mesh.parameter.impl.PagingParametersImpl; import com.gentics.mesh.rest.InternalEndpointRoute; @@ -102,7 +104,7 @@ private void addTagUpdateHandler() { endpoint.produces(APPLICATION_JSON); endpoint.description("Update the specified tag. The tag is created if no tag with the specified uuid could be found."); endpoint.exampleRequest(tagExamples.createTagUpdateRequest("Red")); - endpoint.exampleResponse(OK, tagExamples.createTagResponse1("Red"), "Updated tag."); + endpoint.exampleResponse(OK, tagExamples.createTagResponse1("Red"), "Updated or new tag."); endpoint.events(TAG_UPDATED, TAG_CREATED); endpoint.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); @@ -110,7 +112,6 @@ private void addTagUpdateHandler() { String uuid = PathParameters.getTagUuid(rc); tagCrudHandler.handleUpdate(ac, tagFamilyUuid, uuid); }, isOrderedBlockingHandlers()); - } private void addTagCreateHandler() { @@ -199,8 +200,8 @@ private void addTagRolePermissionHandler() { InternalEndpointRoute grantPermissionsEndpoint = createRoute(); grantPermissionsEndpoint.path("/:tagFamilyUuid/tags/:tagUuid/rolePermissions"); - readPermissionsEndpoint.addUriParameter("tagFamilyUuid", "Uuid of the tag family.", TAGFAMILY_COLORS_UUID); - readPermissionsEndpoint.addUriParameter("tagUuid", "Uuid of the tag.", TAG_BLUE_UUID); + grantPermissionsEndpoint.addUriParameter("tagFamilyUuid", "Uuid of the tag family.", TAGFAMILY_COLORS_UUID); + grantPermissionsEndpoint.addUriParameter("tagUuid", "Uuid of the tag.", TAG_BLUE_UUID); grantPermissionsEndpoint.method(POST); grantPermissionsEndpoint.description("Grant permissions on the tag to multiple roles."); grantPermissionsEndpoint.consumes(APPLICATION_JSON); @@ -215,18 +216,37 @@ private void addTagRolePermissionHandler() { tagCrudHandler.handleGrantPermissions(ac, tagFamilyUuid, uuid); }, isOrderedBlockingHandlers()); - InternalEndpointRoute revokePermissionsEndpoint = createRoute(); - revokePermissionsEndpoint.path("/:tagFamilyUuid/tags/:tagUuid/rolePermissions"); - readPermissionsEndpoint.addUriParameter("tagFamilyUuid", "Uuid of the tag family.", TAGFAMILY_COLORS_UUID); - readPermissionsEndpoint.addUriParameter("tagUuid", "Uuid of the tag.", TAG_BLUE_UUID); - revokePermissionsEndpoint.method(DELETE); - revokePermissionsEndpoint.description("Revoke permissions on the tag from multiple roles."); - revokePermissionsEndpoint.consumes(APPLICATION_JSON); - revokePermissionsEndpoint.produces(APPLICATION_JSON); - revokePermissionsEndpoint.exampleRequest(roleExamples.getObjectPermissionRevokeRequest(false)); - revokePermissionsEndpoint.exampleResponse(OK, roleExamples.getObjectPermissionResponse(false), "Updated permissions."); - revokePermissionsEndpoint.events(ROLE_PERMISSIONS_CHANGED); - revokePermissionsEndpoint.blockingHandler(rc -> { + InternalEndpointRoute revokePermissionsEndpointNonStandard = createRoute(); + revokePermissionsEndpointNonStandard.path("/:tagFamilyUuid/tags/:tagUuid/rolePermissions"); + revokePermissionsEndpointNonStandard.addUriParameter("tagFamilyUuid", "Uuid of the tag family.", TAGFAMILY_COLORS_UUID); + revokePermissionsEndpointNonStandard.addUriParameter("tagUuid", "Uuid of the tag.", TAG_BLUE_UUID); + revokePermissionsEndpointNonStandard.method(DELETE); + revokePermissionsEndpointNonStandard.description("Revoke permissions on the tag from multiple roles."); + revokePermissionsEndpointNonStandard.consumes(APPLICATION_JSON); + revokePermissionsEndpointNonStandard.produces(APPLICATION_JSON); + revokePermissionsEndpointNonStandard.exampleRequest(roleExamples.getObjectPermissionRevokeRequest(false)); + revokePermissionsEndpointNonStandard.exampleResponse(OK, roleExamples.getObjectPermissionResponse(false), "Updated permissions."); + revokePermissionsEndpointNonStandard.events(ROLE_PERMISSIONS_CHANGED); + revokePermissionsEndpointNonStandard.setHidden(true); + revokePermissionsEndpointNonStandard.blockingHandler(rc -> { + InternalActionContext ac = wrap(rc); + String tagFamilyUuid = PathParameters.getTagFamilyUuid(rc); + String uuid = PathParameters.getTagUuid(rc); + tagCrudHandler.handleRevokePermissions(ac, tagFamilyUuid, uuid); + }, isOrderedBlockingHandlers()); + + InternalEndpointRoute revokePermissionsEndpointStandard = createRoute(); + revokePermissionsEndpointStandard.path("/:tagFamilyUuid/tags/:tagUuid/rolePermissions"); + revokePermissionsEndpointStandard.addUriParameter("tagFamilyUuid", "Uuid of the tag family.", TAGFAMILY_COLORS_UUID); + revokePermissionsEndpointStandard.addUriParameter("tagUuid", "Uuid of the tag.", TAG_BLUE_UUID); + revokePermissionsEndpointStandard.method(PUT); + revokePermissionsEndpointStandard.description("Revoke permissions on the tag from multiple roles."); + revokePermissionsEndpointStandard.consumes(APPLICATION_JSON); + revokePermissionsEndpointStandard.produces(APPLICATION_JSON); + revokePermissionsEndpointStandard.exampleRequest(roleExamples.getObjectPermissionRevokeRequest(false)); + revokePermissionsEndpointStandard.exampleResponse(OK, roleExamples.getObjectPermissionResponse(false), "Updated permissions."); + revokePermissionsEndpointStandard.events(ROLE_PERMISSIONS_CHANGED); + revokePermissionsEndpointStandard.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); String tagFamilyUuid = PathParameters.getTagFamilyUuid(rc); String uuid = PathParameters.getTagUuid(rc); @@ -274,6 +294,7 @@ private void addTagFamilyReadHandler() { readOne.path("/:tagFamilyUuid"); readOne.addUriParameter("tagFamilyUuid", "Uuid of the tag family.", TAGFAMILY_COLORS_UUID); readOne.method(GET); + readOne.addQueryParameters(EtagParametersImpl.class); readOne.description("Read the tag family with the given uuid."); readOne.produces(APPLICATION_JSON); readOne.exampleResponse(OK, tagFamilyExamples.getTagFamilyResponse("Colors"), "Loaded tag family."); @@ -321,7 +342,7 @@ private void addTagFamilyUpdateHandler() { endpoint.consumes(APPLICATION_JSON); endpoint.produces(APPLICATION_JSON); endpoint.exampleRequest(tagFamilyExamples.getTagFamilyUpdateRequest("Nicer colors")); - endpoint.exampleResponse(OK, tagFamilyExamples.getTagFamilyResponse("Nicer colors"), "Updated tag family."); + endpoint.exampleResponse(OK, tagFamilyExamples.getTagFamilyResponse("Nicer colors"), "Updated or new tag family."); endpoint.events(TAG_FAMILY_UPDATED, TAG_FAMILY_CREATED); endpoint.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/user/UserEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/user/UserEndpoint.java index 583af10605..da89625972 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/user/UserEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/user/UserEndpoint.java @@ -11,6 +11,7 @@ import static io.vertx.core.http.HttpMethod.DELETE; import static io.vertx.core.http.HttpMethod.GET; import static io.vertx.core.http.HttpMethod.POST; +import static io.vertx.core.http.HttpMethod.PUT; import javax.inject.Inject; @@ -213,8 +214,8 @@ private void addUpdateHandler() { endpoint.produces(APPLICATION_JSON); endpoint.addQueryParameters(UserParametersImpl.class); endpoint.exampleRequest(userExamples.getUserUpdateRequest("jdoe42")); - endpoint.exampleResponse(OK, userExamples.getUserResponse1("jdoe42"), "Updated user response."); - endpoint.events(USER_UPDATED); + endpoint.exampleResponse(OK, userExamples.getUserResponse1("jdoe42"), "Updated or new user response."); + endpoint.events(USER_CREATED, USER_UPDATED); endpoint.blockingHandler(rc -> { InternalActionContext ac = wrap(rc); String uuid = ac.getParameter("userUuid"); diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/webroot/WebRootEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/webroot/WebRootEndpoint.java index 42bda99180..78aecd2197 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/webroot/WebRootEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/webroot/WebRootEndpoint.java @@ -3,9 +3,10 @@ import static com.gentics.mesh.http.HttpConstants.APPLICATION_JSON; import static io.netty.handler.codec.http.HttpResponseStatus.CONFLICT; import static io.netty.handler.codec.http.HttpResponseStatus.CREATED; +import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND; import static io.netty.handler.codec.http.HttpResponseStatus.OK; import static io.vertx.core.http.HttpMethod.GET; -import static io.vertx.core.http.HttpMethod.POST; +import static io.vertx.core.http.HttpMethod.*; import javax.inject.Inject; @@ -77,7 +78,6 @@ private void addPathUpdateCreateHandler() { endpoint.produces(APPLICATION_JSON); endpoint.exampleRequest(nodeExamples.getNodeUpdateRequest()); - endpoint.exampleResponse(OK, nodeExamples.getNodeResponse2(), "Updated node."); endpoint.exampleResponse(CREATED, nodeExamples.getNodeResponse2(), "Created node."); endpoint.exampleResponse(CONFLICT, miscExamples.createMessageResponse(), "A conflict has been detected."); @@ -90,6 +90,7 @@ private void addPathUpdateCreateHandler() { private void addErrorHandlers() { InternalEndpointRoute endpoint = createRoute(); endpoint.path("/error/404"); + endpoint.exampleResponse(NOT_FOUND, "Web root not found"); endpoint.description("Fallback endpoint for unresolvable links which returns 404."); endpoint.handler(rc -> { rc.data().put("statuscode", "404"); diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/webrootfield/WebRootFieldEndpoint.java b/core/src/main/java/com/gentics/mesh/core/endpoint/webrootfield/WebRootFieldEndpoint.java index f233bf3f8a..f695918b47 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/webrootfield/WebRootFieldEndpoint.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/webrootfield/WebRootFieldEndpoint.java @@ -1,5 +1,6 @@ package com.gentics.mesh.core.endpoint.webrootfield; +import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND; import static io.netty.handler.codec.http.HttpResponseStatus.OK; import static io.vertx.core.http.HttpMethod.GET; import static io.vertx.core.http.HttpMethod.POST; @@ -91,6 +92,7 @@ private void addErrorHandlers() { InternalEndpointRoute endpoint = createRoute(); endpoint.path("/error/404"); endpoint.description("Fallback endpoint for unresolvable links which returns 404."); + endpoint.exampleResponse(NOT_FOUND, "Web root field not found"); endpoint.handler(rc -> { rc.data().put("statuscode", "404"); rc.next(); diff --git a/core/src/main/java/com/gentics/mesh/dagger/module/MicrometerModule.java b/core/src/main/java/com/gentics/mesh/dagger/module/MicrometerModule.java index d236687205..08dd7d3101 100644 --- a/core/src/main/java/com/gentics/mesh/dagger/module/MicrometerModule.java +++ b/core/src/main/java/com/gentics/mesh/dagger/module/MicrometerModule.java @@ -90,8 +90,6 @@ private static Optional createTag(String key, String value) { * * @param options * Mesh options - * @param meterRegistry - * Reference to the to be used meter registry * @return */ @Provides diff --git a/core/src/main/java/com/gentics/mesh/generator/AbstractEndpointGenerator.java b/core/src/main/java/com/gentics/mesh/generator/AbstractEndpointGenerator.java new file mode 100644 index 0000000000..ebeba53916 --- /dev/null +++ b/core/src/main/java/com/gentics/mesh/generator/AbstractEndpointGenerator.java @@ -0,0 +1,258 @@ +package com.gentics.mesh.generator; + +import static org.mockito.Mockito.mock; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import org.apache.commons.io.FileUtils; +import org.mockito.Mockito; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.gentics.mesh.core.endpoint.admin.AdminEndpoint; +import com.gentics.mesh.core.endpoint.admin.AdminEndpointImpl; +import com.gentics.mesh.core.endpoint.admin.HealthEndpoint; +import com.gentics.mesh.core.endpoint.admin.RestInfoEndpoint; +import com.gentics.mesh.core.endpoint.auth.AuthenticationEndpoint; +import com.gentics.mesh.core.endpoint.branch.BranchEndpoint; +import com.gentics.mesh.core.endpoint.eventbus.EventbusEndpoint; +import com.gentics.mesh.core.endpoint.group.GroupEndpoint; +import com.gentics.mesh.core.endpoint.microschema.MicroschemaEndpoint; +import com.gentics.mesh.core.endpoint.microschema.ProjectMicroschemaEndpoint; +import com.gentics.mesh.core.endpoint.navroot.NavRootEndpoint; +import com.gentics.mesh.core.endpoint.node.NodeEndpoint; +import com.gentics.mesh.core.endpoint.project.LanguageEndpoint; +import com.gentics.mesh.core.endpoint.project.ProjectEndpoint; +import com.gentics.mesh.core.endpoint.project.ProjectInfoEndpoint; +import com.gentics.mesh.core.endpoint.project.ProjectLanguageEndpoint; +import com.gentics.mesh.core.endpoint.role.RoleEndpoint; +import com.gentics.mesh.core.endpoint.schema.ProjectSchemaEndpoint; +import com.gentics.mesh.core.endpoint.schema.SchemaEndpoint; +import com.gentics.mesh.core.endpoint.tagfamily.TagFamilyEndpoint; +import com.gentics.mesh.core.endpoint.user.UserEndpoint; +import com.gentics.mesh.core.endpoint.utility.UtilityEndpoint; +import com.gentics.mesh.core.endpoint.webroot.WebRootEndpoint; +import com.gentics.mesh.core.endpoint.webrootfield.WebRootFieldEndpoint; +import com.gentics.mesh.etc.config.Format; +import com.gentics.mesh.etc.config.MeshOptions; +import com.gentics.mesh.etc.config.Version; +import com.gentics.mesh.graphql.GraphQLEndpoint; +import com.gentics.mesh.router.APIRouterImpl; +import com.gentics.mesh.router.RootRouterImpl; +import com.gentics.mesh.router.RouterStorageImpl; +import com.gentics.mesh.router.route.AbstractInternalEndpoint; +import com.gentics.mesh.search.ProjectRawSearchEndpointImpl; +import com.gentics.mesh.search.ProjectSearchEndpointImpl; +import com.gentics.mesh.search.RawSearchEndpointImpl; +import com.gentics.mesh.search.SearchEndpointImpl; + +import io.vertx.core.Vertx; +import io.vertx.ext.web.Router; + +public abstract class AbstractEndpointGenerator extends AbstractGenerator { + + private static final Logger log = LoggerFactory.getLogger(AbstractEndpointGenerator.class); + + public AbstractEndpointGenerator() { + } + + public AbstractEndpointGenerator(File outputFolder, boolean cleanup) throws IOException { + super(outputFolder, cleanup); + } + + public AbstractEndpointGenerator(File outputFolder) throws IOException { + super(outputFolder); + } + + /** + * Add all project verticles to the list resources. + * + * @param consumer + * @throws IOException + * @throws Exception + */ + protected void addProjectEndpoints(T consumer) throws IOException { + NodeEndpoint nodeEndpoint = Mockito.spy(new NodeEndpoint()); + initEndpoint(nodeEndpoint); + String projectBasePath = "/{project}"; + addEndpoints(projectBasePath, consumer, nodeEndpoint, true); + + TagFamilyEndpoint tagFamilyEndpoint = Mockito.spy(new TagFamilyEndpoint()); + initEndpoint(tagFamilyEndpoint); + addEndpoints(projectBasePath, consumer, tagFamilyEndpoint, true); + + NavRootEndpoint navEndpoint = Mockito.spy(new NavRootEndpoint()); + initEndpoint(navEndpoint); + addEndpoints(projectBasePath, consumer, navEndpoint, true); + + WebRootEndpoint webEndpoint = Mockito.spy(new WebRootEndpoint()); + initEndpoint(webEndpoint); + addEndpoints(projectBasePath, consumer, webEndpoint, true); + + WebRootFieldEndpoint webFieldEndpoint = Mockito.spy(new WebRootFieldEndpoint()); + initEndpoint(webFieldEndpoint); + addEndpoints(projectBasePath, consumer, webFieldEndpoint, true); + + BranchEndpoint branchEndpoint = Mockito.spy(new BranchEndpoint()); + initEndpoint(branchEndpoint); + addEndpoints(projectBasePath, consumer, branchEndpoint, true); + + GraphQLEndpoint graphqlEndpoint = Mockito.spy(new GraphQLEndpoint()); + initEndpoint(graphqlEndpoint); + addEndpoints(projectBasePath, consumer, graphqlEndpoint, true); + + ProjectSearchEndpointImpl projectSearchEndpoint = Mockito.spy(new ProjectSearchEndpointImpl()); + initEndpoint(projectSearchEndpoint); + addEndpoints(projectBasePath, consumer, projectSearchEndpoint, true); + + ProjectRawSearchEndpointImpl projectRawSearchEndpoint = Mockito.spy(new ProjectRawSearchEndpointImpl()); + initEndpoint(projectRawSearchEndpoint); + addEndpoints(projectBasePath, consumer, projectRawSearchEndpoint, true); + + ProjectSchemaEndpoint projectSchemaEndpoint = Mockito.spy(new ProjectSchemaEndpoint()); + initEndpoint(projectSchemaEndpoint); + addEndpoints(projectBasePath, consumer, projectSchemaEndpoint, true); + + ProjectMicroschemaEndpoint projectMicroschemaEndpoint = Mockito.spy(new ProjectMicroschemaEndpoint()); + initEndpoint(projectMicroschemaEndpoint); + addEndpoints(projectBasePath, consumer, projectMicroschemaEndpoint, true); + + ProjectLanguageEndpoint projectLanguageEndpoint = Mockito.spy(new ProjectLanguageEndpoint()); + initEndpoint(projectLanguageEndpoint); + addEndpoints(projectBasePath, consumer, projectLanguageEndpoint, true); + } + + /** + * Add all core verticles to the map of RAML resources. + * + * @param consumer + * @throws IOException + * @throws Exception + */ + protected void addCoreEndpoints(T consumer) throws IOException { + String coreBasePath = ""; + UserEndpoint userEndpoint = Mockito.spy(new UserEndpoint()); + initEndpoint(userEndpoint); + addEndpoints(coreBasePath, consumer, userEndpoint, false); + + RoleEndpoint roleEndpoint = Mockito.spy(new RoleEndpoint()); + initEndpoint(roleEndpoint); + addEndpoints(coreBasePath, consumer, roleEndpoint, false); + + GroupEndpoint groupEndpoint = Mockito.spy(new GroupEndpoint()); + initEndpoint(groupEndpoint); + addEndpoints(coreBasePath, consumer, groupEndpoint, false); + + ProjectEndpoint projectEndpoint = Mockito.spy(new ProjectEndpoint()); + initEndpoint(projectEndpoint); + addEndpoints(coreBasePath, consumer, projectEndpoint, false); + + SchemaEndpoint schemaEndpoint = Mockito.spy(new SchemaEndpoint()); + initEndpoint(schemaEndpoint); + addEndpoints(coreBasePath, consumer, schemaEndpoint, false); + + MicroschemaEndpoint microschemaEndpoint = Mockito.spy(new MicroschemaEndpoint()); + initEndpoint(microschemaEndpoint); + addEndpoints(coreBasePath, consumer, microschemaEndpoint, false); + + AdminEndpoint adminEndpoint = Mockito.spy(new AdminEndpointImpl()); + initEndpoint(adminEndpoint); + addEndpoints(coreBasePath, consumer, adminEndpoint, false); + + HealthEndpoint healthEndpoint = Mockito.spy(new HealthEndpoint()); + initEndpoint(healthEndpoint); + addEndpoints(coreBasePath, consumer, healthEndpoint, false); + + SearchEndpointImpl searchEndpoint = Mockito.spy(new SearchEndpointImpl()); + initEndpoint(searchEndpoint); + addEndpoints(coreBasePath, consumer, searchEndpoint, false); + + RawSearchEndpointImpl rawSearchEndpoint = Mockito.spy(new RawSearchEndpointImpl()); + initEndpoint(rawSearchEndpoint); + addEndpoints(coreBasePath, consumer, rawSearchEndpoint, false); + + UtilityEndpoint utilityEndpoint = Mockito.spy(new UtilityEndpoint()); + initEndpoint(utilityEndpoint); + addEndpoints(coreBasePath, consumer, utilityEndpoint, false); + + AuthenticationEndpoint authEndpoint = Mockito.spy(new AuthenticationEndpoint()); + initEndpoint(authEndpoint); + addEndpoints(coreBasePath, consumer, authEndpoint, false); + + EventbusEndpoint eventbusEndpoint = Mockito.spy(new EventbusEndpoint()); + initEndpoint(eventbusEndpoint); + addEndpoints(coreBasePath, consumer, eventbusEndpoint, false); + + RouterStorageImpl rs = Mockito.mock(RouterStorageImpl.class); + RootRouterImpl rootRouter = Mockito.mock(RootRouterImpl.class); + Mockito.when(rs.root()).thenReturn(rootRouter); + APIRouterImpl apiRouter = Mockito.mock(APIRouterImpl.class); + Mockito.when(rootRouter.apiRouter()).thenReturn(apiRouter); + RestInfoEndpoint infoEndpoint = Mockito.spy(new RestInfoEndpoint("")); + infoEndpoint.init(null, rs); + initEndpoint(infoEndpoint); + addEndpoints(coreBasePath, consumer, infoEndpoint, false); + + ProjectInfoEndpoint projectInfoEndpoint = Mockito.spy(new ProjectInfoEndpoint()); + initEndpoint(projectInfoEndpoint); + addEndpoints(coreBasePath, consumer, projectInfoEndpoint, false); + + LanguageEndpoint languageEndpoint = Mockito.spy(new LanguageEndpoint()); + initEndpoint(languageEndpoint); + addEndpoints(coreBasePath, consumer, languageEndpoint, false); + } + + /** + * Add any extra verticles to the consumer. + * + * @param resources + * @throws IOException + */ + protected void addExtraEndpoints(T consumer) throws IOException { + } + + /** + * Add an endpoint to the data consumer. + * + * @param coreBasePath + * @param consumer + * @param projectInfoEndpoint + * @param isProject + * @throws IOException + */ + protected abstract void addEndpoints(String coreBasePath, T consumer, AbstractInternalEndpoint projectInfoEndpoint, boolean isProject) throws IOException; + + /** + * Mock an endpoint with data, full enough for the generator to succeed. + * + * @param endpoint + */ + protected void initEndpoint(AbstractInternalEndpoint endpoint) { + Vertx vertx = mock(Vertx.class); + MeshOptions options = mock(MeshOptions.class); + Mockito.when(endpoint.getRouter()).thenReturn(Router.router(vertx)); + Mockito.when(endpoint.getOptions()).thenReturn(options); + Mockito.when(options.getDefaultOpenAPIFormat()).thenReturn(Format.YAML); + Mockito.when(options.getDefaultOpenAPIVersion()).thenReturn(Version.V30); + endpoint.registerEndPoints(); + } + + /** + * Save the string content to the given file in the output folder. + * + * @param filename + * Name of the file to be written to + * @param content + * Content to be written + * @throws IOException + */ + public void writeFile(String filename, String content) throws IOException { + if (outputFolder != null) { + File outputFile = new File(outputFolder, filename); + FileUtils.writeStringToFile(outputFile, content, StandardCharsets.UTF_8); + log.info("File saved to {" + outputFile.getPath() + "}"); + } + } +} diff --git a/core/src/main/java/com/gentics/mesh/generator/OpenAPIMockAPIGenerator.java b/core/src/main/java/com/gentics/mesh/generator/OpenAPIMockAPIGenerator.java new file mode 100644 index 0000000000..aeba46c75b --- /dev/null +++ b/core/src/main/java/com/gentics/mesh/generator/OpenAPIMockAPIGenerator.java @@ -0,0 +1,84 @@ +package com.gentics.mesh.generator; + +import static com.gentics.mesh.MeshVersion.CURRENT_API_VERSION; +import static org.apache.commons.lang3.StringUtils.isEmpty; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.gentics.mesh.MeshVersion; +import com.gentics.mesh.router.route.AbstractInternalEndpoint; +import com.gentics.mesh.util.MeshOpenAPIv3Generator; +import com.gentics.vertx.openapi.OpenAPIv3Generator; +import com.gentics.vertx.openapi.model.Format; +import com.gentics.vertx.openapi.model.OpenAPIGenerationException; + +import io.vertx.ext.web.Router; + +/** + * OpenAPI v3 API definition generator. Outputs JSON and YAML schemas. + * + * @author plyhun + * + */ +public class OpenAPIMockAPIGenerator extends AbstractEndpointGenerator { + + private static final Logger log = LoggerFactory.getLogger(OpenAPIMockAPIGenerator.class); + + private final MeshOpenAPIv3Generator generator; + private final Map routers = new HashMap<>(); + private final String fileName; + + public OpenAPIMockAPIGenerator() { + super(); + this.fileName = null; + this.generator = new MeshOpenAPIv3Generator(MeshVersion.getPlainVersion(), Collections.emptyList(), Optional.empty(), Optional.empty()); + } + + public OpenAPIMockAPIGenerator(File outputFolder, String fileName, boolean cleanup) throws IOException { + super(new File(outputFolder, "api"), cleanup); + this.fileName = fileName; + this.generator = new MeshOpenAPIv3Generator(MeshVersion.getPlainVersion(), Collections.emptyList(), Optional.empty(), Optional.empty()); + } + + public OpenAPIMockAPIGenerator(File outputFolder, String fileName) throws IOException { + this(outputFolder, fileName, false); + } + + public String generate(String format) throws IOException, OpenAPIGenerationException { + log.info("Starting OpenAPIv3 generation..."); + addCoreEndpoints(generator); + addProjectEndpoints(generator); + addExtraEndpoints(generator); + + return generator.generate(routers, Format.parse(format), true, false); + } + + @Override + protected void addEndpoints(String basePath, OpenAPIv3Generator consumer, AbstractInternalEndpoint verticle, + boolean isProject) throws IOException { + String fullPath = "/api/v" + CURRENT_API_VERSION + basePath + "/" + verticle.getBasePath(); + if (isEmpty(verticle.getBasePath())) { + fullPath = "/api/v" + CURRENT_API_VERSION + basePath; + } + routers.put(verticle.getRouter(), fullPath); + } + + /** + * Start the generator. + * + * @throws IOException + * @throws OpenAPIGenerationException + */ + public void run() throws IOException, OpenAPIGenerationException { + String yaml = generate("yaml"); + writeFile(fileName, yaml); + } +} diff --git a/core/src/main/java/com/gentics/mesh/generator/RAMLGenerator.java b/core/src/main/java/com/gentics/mesh/generator/RAMLGenerator.java index 6fd6067964..ccdfdc2e9a 100644 --- a/core/src/main/java/com/gentics/mesh/generator/RAMLGenerator.java +++ b/core/src/main/java/com/gentics/mesh/generator/RAMLGenerator.java @@ -2,7 +2,6 @@ import static com.gentics.mesh.MeshVersion.CURRENT_API_VERSION; import static org.apache.commons.lang3.StringUtils.isEmpty; -import static org.mockito.Mockito.mock; import java.io.File; import java.io.IOException; @@ -12,8 +11,6 @@ import java.util.function.BiConsumer; import java.util.stream.Collectors; -import org.apache.commons.io.FileUtils; -import org.mockito.Mockito; import org.raml.emitter.RamlEmitter; import org.raml.model.Action; import org.raml.model.ActionType; @@ -26,47 +23,15 @@ import org.slf4j.LoggerFactory; import com.gentics.mesh.MeshVersion; -import com.gentics.mesh.core.endpoint.admin.AdminEndpoint; -import com.gentics.mesh.core.endpoint.admin.AdminEndpointImpl; -import com.gentics.mesh.core.endpoint.admin.HealthEndpoint; -import com.gentics.mesh.core.endpoint.admin.RestInfoEndpoint; -import com.gentics.mesh.core.endpoint.auth.AuthenticationEndpoint; -import com.gentics.mesh.core.endpoint.branch.BranchEndpoint; -import com.gentics.mesh.core.endpoint.eventbus.EventbusEndpoint; -import com.gentics.mesh.core.endpoint.group.GroupEndpoint; -import com.gentics.mesh.core.endpoint.microschema.MicroschemaEndpoint; -import com.gentics.mesh.core.endpoint.microschema.ProjectMicroschemaEndpoint; -import com.gentics.mesh.core.endpoint.navroot.NavRootEndpoint; -import com.gentics.mesh.core.endpoint.node.NodeEndpoint; -import com.gentics.mesh.core.endpoint.project.ProjectEndpoint; -import com.gentics.mesh.core.endpoint.project.ProjectInfoEndpoint; -import com.gentics.mesh.core.endpoint.role.RoleEndpoint; -import com.gentics.mesh.core.endpoint.schema.ProjectSchemaEndpoint; -import com.gentics.mesh.core.endpoint.schema.SchemaEndpoint; -import com.gentics.mesh.core.endpoint.tagfamily.TagFamilyEndpoint; -import com.gentics.mesh.core.endpoint.user.UserEndpoint; -import com.gentics.mesh.core.endpoint.utility.UtilityEndpoint; -import com.gentics.mesh.core.endpoint.webroot.WebRootEndpoint; -import com.gentics.mesh.core.endpoint.webrootfield.WebRootFieldEndpoint; -import com.gentics.mesh.graphql.GraphQLEndpoint; import com.gentics.mesh.rest.InternalEndpointRoute; -import com.gentics.mesh.router.APIRouterImpl; -import com.gentics.mesh.router.RootRouterImpl; -import com.gentics.mesh.router.RouterStorageImpl; import com.gentics.mesh.router.route.AbstractInternalEndpoint; -import com.gentics.mesh.search.ProjectRawSearchEndpointImpl; -import com.gentics.mesh.search.ProjectSearchEndpointImpl; -import com.gentics.mesh.search.RawSearchEndpointImpl; -import com.gentics.mesh.search.SearchEndpointImpl; -import io.vertx.core.Vertx; import io.vertx.core.http.HttpMethod; -import io.vertx.ext.web.Router; /** * Generator for RAML documentation. The generation mocks all endpoint classes and extracts the routes from these endpoints in order to generate the RAML. */ -public class RAMLGenerator extends AbstractGenerator { +public class RAMLGenerator extends AbstractEndpointGenerator> { private static final Logger log = LoggerFactory.getLogger(RAMLGenerator.class); @@ -139,8 +104,7 @@ public String generate() { * Endpoint which provides endpoints * @throws IOException */ - protected void addEndpoints(String basePath, Map resources, AbstractInternalEndpoint verticle) throws IOException { - + protected void addEndpoints(String basePath, Map resources, AbstractInternalEndpoint verticle, boolean isProject) throws IOException { String ramlPath = basePath + "/" + verticle.getBasePath(); // Check whether the resource was already added. Maybe we just need to extend it Resource verticleResource = resources.get(ramlPath); @@ -247,23 +211,6 @@ protected void addEndpoints(String basePath, Map resources, Ab } - /** - * Save the string content to the given file in the output folder. - * - * @param filename - * Name of the file to be written to - * @param content - * Content to be written - * @throws IOException - */ - public void writeFile(String filename, String content) throws IOException { - if (outputFolder != null) { - File outputFile = new File(outputFolder, filename); - FileUtils.writeStringToFile(outputFile, content); - log.info("File saved to {" + outputFile.getPath() + "}"); - } - } - /** * Convert the http method to a RAML action type. * @@ -274,153 +221,6 @@ protected ActionType getActionType(HttpMethod method) { return ActionType.valueOf(method.name()); } - protected void initEndpoint(AbstractInternalEndpoint endpoint) { - Vertx vertx = mock(Vertx.class); - Mockito.when(endpoint.getRouter()).thenReturn(Router.router(vertx)); - endpoint.registerEndPoints(); - } - - /** - * Add all project verticles to the list resources. - * - * @param resources - * @throws IOException - * @throws Exception - */ - protected void addProjectEndpoints(Map resources) throws IOException { - NodeEndpoint nodeEndpoint = Mockito.spy(new NodeEndpoint()); - initEndpoint(nodeEndpoint); - String projectBasePath = "/{project}"; - addEndpoints(projectBasePath, resources, nodeEndpoint); - - TagFamilyEndpoint tagFamilyEndpoint = Mockito.spy(new TagFamilyEndpoint()); - initEndpoint(tagFamilyEndpoint); - addEndpoints(projectBasePath, resources, tagFamilyEndpoint); - - NavRootEndpoint navEndpoint = Mockito.spy(new NavRootEndpoint()); - initEndpoint(navEndpoint); - addEndpoints(projectBasePath, resources, navEndpoint); - - WebRootEndpoint webEndpoint = Mockito.spy(new WebRootEndpoint()); - initEndpoint(webEndpoint); - addEndpoints(projectBasePath, resources, webEndpoint); - - WebRootFieldEndpoint webFieldEndpoint = Mockito.spy(new WebRootFieldEndpoint()); - initEndpoint(webFieldEndpoint); - addEndpoints(projectBasePath, resources, webFieldEndpoint); - - BranchEndpoint branchEndpoint = Mockito.spy(new BranchEndpoint()); - initEndpoint(branchEndpoint); - addEndpoints(projectBasePath, resources, branchEndpoint); - - GraphQLEndpoint graphqlEndpoint = Mockito.spy(new GraphQLEndpoint()); - initEndpoint(graphqlEndpoint); - addEndpoints(projectBasePath, resources, graphqlEndpoint); - - ProjectSearchEndpointImpl projectSearchEndpoint = Mockito.spy(new ProjectSearchEndpointImpl()); - initEndpoint(projectSearchEndpoint); - addEndpoints(projectBasePath, resources, projectSearchEndpoint); - - ProjectRawSearchEndpointImpl projectRawSearchEndpoint = Mockito.spy(new ProjectRawSearchEndpointImpl()); - initEndpoint(projectRawSearchEndpoint); - addEndpoints(projectBasePath, resources, projectRawSearchEndpoint); - - ProjectSchemaEndpoint projectSchemaEndpoint = Mockito.spy(new ProjectSchemaEndpoint()); - initEndpoint(projectSchemaEndpoint); - addEndpoints(projectBasePath, resources, projectSchemaEndpoint); - - ProjectMicroschemaEndpoint projectMicroschemaEndpoint = Mockito.spy(new ProjectMicroschemaEndpoint()); - initEndpoint(projectMicroschemaEndpoint); - addEndpoints(projectBasePath, resources, projectMicroschemaEndpoint); - - } - - /** - * Add all core verticles to the map of RAML resources. - * - * @param resources - * @throws IOException - * @throws Exception - */ - protected void addCoreEndpoints(Map resources) throws IOException { - String coreBasePath = ""; - UserEndpoint userEndpoint = Mockito.spy(new UserEndpoint()); - initEndpoint(userEndpoint); - addEndpoints(coreBasePath, resources, userEndpoint); - - RoleEndpoint roleEndpoint = Mockito.spy(new RoleEndpoint()); - initEndpoint(roleEndpoint); - addEndpoints(coreBasePath, resources, roleEndpoint); - - GroupEndpoint groupEndpoint = Mockito.spy(new GroupEndpoint()); - initEndpoint(groupEndpoint); - addEndpoints(coreBasePath, resources, groupEndpoint); - - ProjectEndpoint projectEndpoint = Mockito.spy(new ProjectEndpoint()); - initEndpoint(projectEndpoint); - addEndpoints(coreBasePath, resources, projectEndpoint); - - SchemaEndpoint schemaEndpoint = Mockito.spy(new SchemaEndpoint()); - initEndpoint(schemaEndpoint); - addEndpoints(coreBasePath, resources, schemaEndpoint); - - MicroschemaEndpoint microschemaEndpoint = Mockito.spy(new MicroschemaEndpoint()); - initEndpoint(microschemaEndpoint); - addEndpoints(coreBasePath, resources, microschemaEndpoint); - - AdminEndpoint adminEndpoint = Mockito.spy(new AdminEndpointImpl()); - initEndpoint(adminEndpoint); - addEndpoints(coreBasePath, resources, adminEndpoint); - - HealthEndpoint healthEndpoint = Mockito.spy(new HealthEndpoint()); - initEndpoint(healthEndpoint); - addEndpoints(coreBasePath, resources, healthEndpoint); - - SearchEndpointImpl searchEndpoint = Mockito.spy(new SearchEndpointImpl()); - initEndpoint(searchEndpoint); - addEndpoints(coreBasePath, resources, searchEndpoint); - - RawSearchEndpointImpl rawSearchEndpoint = Mockito.spy(new RawSearchEndpointImpl()); - initEndpoint(rawSearchEndpoint); - addEndpoints(coreBasePath, resources, rawSearchEndpoint); - - UtilityEndpoint utilityEndpoint = Mockito.spy(new UtilityEndpoint()); - initEndpoint(utilityEndpoint); - addEndpoints(coreBasePath, resources, utilityEndpoint); - - AuthenticationEndpoint authEndpoint = Mockito.spy(new AuthenticationEndpoint()); - initEndpoint(authEndpoint); - addEndpoints(coreBasePath, resources, authEndpoint); - - EventbusEndpoint eventbusEndpoint = Mockito.spy(new EventbusEndpoint()); - initEndpoint(eventbusEndpoint); - addEndpoints(coreBasePath, resources, eventbusEndpoint); - - RouterStorageImpl rs = Mockito.mock(RouterStorageImpl.class); - RootRouterImpl rootRouter = Mockito.mock(RootRouterImpl.class); - Mockito.when(rs.root()).thenReturn(rootRouter); - APIRouterImpl apiRouter = Mockito.mock(APIRouterImpl.class); - Mockito.when(rootRouter.apiRouter()).thenReturn(apiRouter); - RestInfoEndpoint infoEndpoint = Mockito.spy(new RestInfoEndpoint("")); - infoEndpoint.init(null, rs); - initEndpoint(infoEndpoint); - addEndpoints(coreBasePath, resources, infoEndpoint); - - ProjectInfoEndpoint projectInfoEndpoint = Mockito.spy(new ProjectInfoEndpoint()); - initEndpoint(projectInfoEndpoint); - addEndpoints(coreBasePath, resources, projectInfoEndpoint); - - } - - /** - * Add any extra verticles to the map of RAML resources. - * - * @param resources - * @throws IOException - */ - protected void addExtraEndpoints(Map resources) throws IOException { - } - /** * Start the generator. * diff --git a/core/src/main/java/com/gentics/mesh/generator/runner/OpenAPISpecGeneratorRunner.java b/core/src/main/java/com/gentics/mesh/generator/runner/OpenAPISpecGeneratorRunner.java new file mode 100644 index 0000000000..2aa205574b --- /dev/null +++ b/core/src/main/java/com/gentics/mesh/generator/runner/OpenAPISpecGeneratorRunner.java @@ -0,0 +1,38 @@ +package com.gentics.mesh.generator.runner; + +import java.io.File; + +import com.gentics.mesh.generator.OpenAPIMockAPIGenerator; + +public class OpenAPISpecGeneratorRunner { + + private static final long SPEC_AGE_MILLIS = 1000 * 60 * 5; + + /** + * Start the generator. + * + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + if (args == null || args.length < 1) { + System.err.println("OpenAPISpecGeneratorRunner: no output folder provided"); + return; + } + final File outputFolder = new File(args[0]); + + if (!outputFolder.exists()) { + outputFolder.mkdirs(); + } else { + File openapiYaml = new File(outputFolder, "openapi.yaml"); + if (openapiYaml.exists() && (openapiYaml.lastModified() - System.currentTimeMillis()) < SPEC_AGE_MILLIS) { + System.out.println("OpenAPISpecGeneratorRunner: openapi.yaml is fresh enough, no generation required"); + return; + } + } + + // Generate OpenAPI base spec + OpenAPIMockAPIGenerator openApiGenerator = new OpenAPIMockAPIGenerator(outputFolder, "openapi.yaml", false); + openApiGenerator.run(); + } +} diff --git a/core/src/main/java/com/gentics/mesh/plugin/registry/RestPluginRegistry.java b/core/src/main/java/com/gentics/mesh/plugin/registry/RestPluginRegistry.java index d71fc9058b..286eec9c48 100644 --- a/core/src/main/java/com/gentics/mesh/plugin/registry/RestPluginRegistry.java +++ b/core/src/main/java/com/gentics/mesh/plugin/registry/RestPluginRegistry.java @@ -10,18 +10,18 @@ import javax.inject.Inject; import javax.inject.Singleton; +import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.gentics.mesh.core.rest.error.GenericRestException; import com.gentics.mesh.plugin.MeshPlugin; import com.gentics.mesh.plugin.RestPlugin; import com.gentics.mesh.router.PluginRouter; -import com.gentics.mesh.router.PluginRouterImpl; import com.gentics.mesh.router.RouterStorage; -import com.gentics.mesh.router.RouterStorageImpl; import com.gentics.mesh.router.RouterStorageRegistryImpl; import io.reactivex.Completable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import io.vertx.ext.web.Router; /** @@ -57,19 +57,19 @@ public Completable register(MeshPlugin plugin) { PluginRouter globalPluginRouter = rs.root().apiRouter().pluginRouter(); PluginRouter projectPluginRouter = rs.root().apiRouter().projectsRouter().projectRouter().pluginRouter(); - Router globalRouter = restPlugin.createGlobalRouter(); + Pair routers = restPlugin.createRouters(); + Router globalRouter = routers.getLeft(); if (globalRouter != null) { globalPluginRouter.addRouter(apiName, globalRouter); log.info("Registering REST API Plugin {" + name + "} for globally"); } - Router projectRouter = restPlugin.createProjectRouter(); + Router projectRouter = routers.getRight(); if (projectRouter != null) { projectPluginRouter.addRouter(apiName, projectRouter); log.info("Registering REST API Plugin {" + name + "} for projects"); } } } - sub.onComplete(); }).doOnError(error -> { if (error instanceof GenericRestException) { diff --git a/core/src/main/java/com/gentics/mesh/rest/MeshLocalClientImpl.java b/core/src/main/java/com/gentics/mesh/rest/MeshLocalClientImpl.java index 21254dafe7..0f36c23e54 100644 --- a/core/src/main/java/com/gentics/mesh/rest/MeshLocalClientImpl.java +++ b/core/src/main/java/com/gentics/mesh/rest/MeshLocalClientImpl.java @@ -123,7 +123,6 @@ import com.gentics.mesh.core.rest.user.UserResponse; import com.gentics.mesh.core.rest.user.UserUpdateRequest; import com.gentics.mesh.core.rest.validation.SchemaValidationResponse; -import com.gentics.mesh.parameter.BackupParameters; import com.gentics.mesh.parameter.ImageManipulationParameters; import com.gentics.mesh.parameter.PagingParameters; import com.gentics.mesh.parameter.ParameterProvider; @@ -405,8 +404,8 @@ public MeshRequest findTagByUuid(String projectName, String tagFami } @Override - public MeshRequest updateTag(String projectName, String tagFamilyUuid, String uuid, TagUpdateRequest request) { - LocalActionContextImpl ac = createContext(TagResponse.class); + public MeshRequest updateTag(String projectName, String tagFamilyUuid, String uuid, TagUpdateRequest request, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(TagResponse.class, parameters); ac.setProject(projectName); ac.setPayloadObject(request); ac.setParameter("tagUuid", uuid); @@ -468,15 +467,13 @@ public MeshRequest findProjects(ParameterProvider... parame @Override @Deprecated - public MeshRequest assignLanguageToProject(String projectUuid, String languageUuid) { - return assignLanguageToProjectByUuid(projectUuid, languageUuid); + public MeshRequest assignLanguageToProject(String projectUuid, String languageUuid, ParameterProvider... parameters) { + return assignLanguageToProjectByUuid(projectUuid, languageUuid, parameters); } @Override - public MeshRequest unassignLanguageFromProject(String projectUuid, String languageUuid) { - LocalActionContextImpl ac = createContext(ProjectResponse.class); - // TODO add implementation - return new MeshLocalRequestImpl<>(ac.getFuture()); + public MeshRequest unassignLanguageFromProject(String projectUuid, String languageUuid, ParameterProvider... parameters) { + return unassignLanguageFromProjectByUuid(projectUuid, languageUuid, parameters); } @Override @@ -496,8 +493,8 @@ public MeshRequest createProject(String uuid, ProjectCreateRequ } @Override - public MeshRequest updateProject(String uuid, ProjectUpdateRequest request) { - LocalActionContextImpl ac = createContext(ProjectResponse.class); + public MeshRequest updateProject(String uuid, ProjectUpdateRequest request, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(ProjectResponse.class, parameters); projectCrudHandler.handleUpdate(ac, uuid); return new MeshLocalRequestImpl<>(ac.getFuture()); } @@ -593,8 +590,8 @@ public MeshRequest deleteTagFamily(String projectName, String uui } @Override - public MeshRequest updateTagFamily(String projectName, String tagFamilyUuid, TagFamilyUpdateRequest request) { - LocalActionContextImpl ac = createContext(TagFamilyResponse.class); + public MeshRequest updateTagFamily(String projectName, String tagFamilyUuid, TagFamilyUpdateRequest request, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(TagFamilyResponse.class, parameters); ac.setPayloadObject(request); ac.setProject(projectName); tagFamilyCrudHandler.handleUpdate(ac, tagFamilyUuid); @@ -799,8 +796,8 @@ public MeshRequest createGroup(String uuid, GroupCreateRequest cr } @Override - public MeshRequest updateGroup(String uuid, GroupUpdateRequest request) { - LocalActionContextImpl ac = createContext(GroupResponse.class); + public MeshRequest updateGroup(String uuid, GroupUpdateRequest request, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(GroupResponse.class, parameters); ac.setPayloadObject(request); groupCrudHandler.handleUpdate(ac, uuid); return new MeshLocalRequestImpl<>(ac.getFuture()); @@ -959,8 +956,8 @@ public MeshRequest readRolePermissions(String roleUuid, } @Override - public MeshRequest updateRole(String uuid, RoleUpdateRequest restRole) { - LocalActionContextImpl ac = createContext(RoleResponse.class); + public MeshRequest updateRole(String uuid, RoleUpdateRequest restRole, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(RoleResponse.class, parameters); ac.setPayloadObject(restRole); roleCrudHandler.handleUpdate(ac, uuid); return new MeshLocalRequestImpl<>(ac.getFuture()); @@ -1004,8 +1001,8 @@ public MeshRequest searchUsers(String json, ParameterProvider. } @Override - public MeshRequest searchUsersRaw(String json) { - LocalActionContextImpl ac = createContext(ObjectNode.class); + public MeshRequest searchUsersRaw(String json, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(ObjectNode.class, parameters); return new MeshLocalRequestImpl<>(ac.getFuture()); } @@ -1016,8 +1013,8 @@ public MeshRequest searchGroups(String json, ParameterProvide } @Override - public MeshRequest searchGroupsRaw(String json) { - LocalActionContextImpl ac = createContext(ObjectNode.class); + public MeshRequest searchGroupsRaw(String json, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(ObjectNode.class, parameters); return new MeshLocalRequestImpl<>(ac.getFuture()); } @@ -1029,8 +1026,8 @@ public MeshRequest searchRoles(String json, ParameterProvider. } @Override - public MeshRequest searchRolesRaw(String json) { - LocalActionContextImpl ac = createContext(ObjectNode.class); + public MeshRequest searchRolesRaw(String json, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(ObjectNode.class, parameters); return new MeshLocalRequestImpl<>(ac.getFuture()); } @@ -1042,8 +1039,8 @@ public MeshRequest searchProjects(String json, ParameterPro } @Override - public MeshRequest searchProjectsRaw(String json) { - LocalActionContextImpl ac = createContext(ObjectNode.class); + public MeshRequest searchProjectsRaw(String json, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(ObjectNode.class, parameters); return new MeshLocalRequestImpl<>(ac.getFuture()); } @@ -1054,8 +1051,8 @@ public MeshRequest searchTags(String json, ParameterProvider... } @Override - public MeshRequest searchTagsRaw(String json) { - LocalActionContextImpl ac = createContext(ObjectNode.class); + public MeshRequest searchTagsRaw(String json, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(ObjectNode.class, parameters); return new MeshLocalRequestImpl<>(ac.getFuture()); } @@ -1066,8 +1063,8 @@ public MeshRequest searchTagFamilies(String json, Paramet } @Override - public MeshRequest searchTagFamiliesRaw(String projectName, String json) { - LocalActionContextImpl ac = createContext(ObjectNode.class); + public MeshRequest searchTagFamiliesRaw(String projectName, String json, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(ObjectNode.class, parameters); return new MeshLocalRequestImpl<>(ac.getFuture()); } @@ -1078,8 +1075,8 @@ public MeshRequest searchSchemas(String json, ParameterProvi } @Override - public MeshRequest searchSchemasRaw(String json) { - LocalActionContextImpl ac = createContext(ObjectNode.class); + public MeshRequest searchSchemasRaw(String json, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(ObjectNode.class, parameters); return new MeshLocalRequestImpl<>(ac.getFuture()); } @@ -1090,8 +1087,8 @@ public MeshRequest searchMicroschemas(String json, Para } @Override - public MeshRequest searchMicroschemasRaw(String json) { - LocalActionContextImpl ac = createContext(ObjectNode.class); + public MeshRequest searchMicroschemasRaw(String json, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(ObjectNode.class, parameters); return new MeshLocalRequestImpl<>(ac.getFuture()); } @@ -1477,13 +1474,17 @@ public MeshRequest findBranches(String projectName, Paramete } @Override - public MeshRequest updateBranch(String projectName, String branchUuid, BranchUpdateRequest request) { - // TODO Auto-generated method stub - return null; + public MeshRequest updateBranch(String projectName, String branchUuid, BranchUpdateRequest request, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(BranchResponse.class, parameters); + ac.setProject(projectName); + ac.setPayloadObject(request); + ac.setParameter("uuid", branchUuid); + branchCrudHandler.handleUpdate(ac, branchUuid); + return new MeshLocalRequestImpl<>(ac.getFuture()); } @Override - public MeshRequest getBranchSchemaVersions(String projectName, String branchUuid) { + public MeshRequest getBranchSchemaVersions(String projectName, String branchUuid, ParameterProvider... parameters) { // TODO Auto-generated method stub return null; } @@ -1506,7 +1507,7 @@ public MeshRequest assignBranchSchemaVersions(String proje } @Override - public MeshRequest getBranchMicroschemaVersions(String projectName, String branchUuid) { + public MeshRequest getBranchMicroschemaVersions(String projectName, String branchUuid, ParameterProvider... parameters) { // TODO Auto-generated method stub return null; } @@ -1592,8 +1593,8 @@ public MeshRequest searchTags(String projectName, String json, } @Override - public MeshRequest searchTagsRaw(String projectName, String json) { - LocalActionContextImpl ac = createContext(ObjectNode.class); + public MeshRequest searchTagsRaw(String projectName, String json, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(ObjectNode.class, parameters); return new MeshLocalRequestImpl<>(ac.getFuture()); } @@ -1604,8 +1605,8 @@ public MeshRequest searchTagFamilies(String projectName, } @Override - public MeshRequest searchTagFamiliesRaw(String json) { - LocalActionContextImpl ac = createContext(ObjectNode.class); + public MeshRequest searchTagFamiliesRaw(String json, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(ObjectNode.class, parameters); return new MeshLocalRequestImpl<>(ac.getFuture()); } @@ -1622,37 +1623,13 @@ public MeshRequest getRAML() { } @Override - public MeshRequest graphql(String projectName, GraphQLRequest request, ParameterProvider... parameters) { - // TODO Auto-generated method stub - return null; - } - - @Override - public MeshRequest invokeBackup() { - // TODO Auto-generated method stub - return null; - } - - @Override - public MeshRequest invokeBackup(BackupParameters backupParameters) { + public MeshRequest getOpenAPI() { // TODO Auto-generated method stub return null; } @Override - public MeshRequest invokeExport() { - // TODO Auto-generated method stub - return null; - } - - @Override - public MeshRequest invokeRestore() { - // TODO Auto-generated method stub - return null; - } - - @Override - public MeshRequest invokeImport() { + public MeshRequest graphql(String projectName, GraphQLRequest request, ParameterProvider... parameters) { // TODO Auto-generated method stub return null; } @@ -2028,8 +2005,8 @@ public MeshRequest revokeProjectRolePermissions(String } @Override - public MeshRequest getRoleRolePermissions(String uuid) { - LocalActionContextImpl ac = createContext(ObjectPermissionResponse.class); + public MeshRequest getRoleRolePermissions(String uuid, ParameterProvider... parameters) { + LocalActionContextImpl ac = createContext(ObjectPermissionResponse.class, parameters); roleCrudHandler.handleReadPermissions(ac, uuid); return new MeshLocalRequestImpl<>(ac.getFuture()); } diff --git a/core/src/main/resources/logback.xml b/core/src/main/resources/logback.xml index 3159433ef1..ad969a6c4a 100644 --- a/core/src/main/resources/logback.xml +++ b/core/src/main/resources/logback.xml @@ -19,7 +19,7 @@ - + diff --git a/doc/src/main/hugo/content/docs/references.asciidoc b/doc/src/main/hugo/content/docs/references.asciidoc index c75a97d820..81160253e7 100644 --- a/doc/src/main/hugo/content/docs/references.asciidoc +++ b/doc/src/main/hugo/content/docs/references.asciidoc @@ -19,6 +19,17 @@ There are many things you can do with the REST API. To name a few: NOTE: All REST API responses are available in JSON, only, except for binary data. +=== OpenAPI Specification + +The link:https://swagger.io/specification/[OpenAPI specification] is available for Gentics Mesh in two variants: + +* The generic link:https://spec.openapis.org/oas/v3.0.0.html[OpenAPI v3.0 specification], unrelated to any actual Gentics Mesh installation, can be checked right link:/docs/api/openapi.yaml[here] in the YAML format. +* The installation-aware specification, which is generated right in Mesh at runtime, and, in addition to the generic specification, contains also the endpoints of all the plugins currently running along, as well as some technical info of an installation (servers). + +=== RAML Specification + +The link:https://github.com/raml-org/raml-spec/blob/master/versions/raml-08/raml-08.md[RAML v0.8 specification] provides the generic REST API information, and can be checked link:/docs/api/api.raml[here]. + === Query Parameters The REST API end points can be used in combination with a set of query parameters, all of which are documented for the specific end points in the link:/docs/api[Gentics Mesh REST API] reference. Following, we provide an overview of the most common query parameters. diff --git a/doc/src/main/java/com/gentics/mesh/generator/DocGeneratorRunner.java b/doc/src/main/java/com/gentics/mesh/generator/DocGeneratorRunner.java index 1faad07af1..679beeb30f 100644 --- a/doc/src/main/java/com/gentics/mesh/generator/DocGeneratorRunner.java +++ b/doc/src/main/java/com/gentics/mesh/generator/DocGeneratorRunner.java @@ -1,12 +1,6 @@ package com.gentics.mesh.generator; -import com.gentics.mesh.etc.config.env.EnvironmentVariable; -import com.gentics.mesh.generator.TableGenerator; -import com.github.jknack.handlebars.Handlebars; -import com.github.jknack.handlebars.Template; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.reflections.Reflections; +import static org.reflections.scanners.Scanners.FieldsAnnotated; import java.io.File; import java.io.IOException; @@ -19,7 +13,13 @@ import java.util.Map; import java.util.Objects; -import static org.reflections.scanners.Scanners.FieldsAnnotated; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.reflections.Reflections; + +import com.gentics.mesh.etc.config.env.EnvironmentVariable; +import com.github.jknack.handlebars.Handlebars; +import com.github.jknack.handlebars.Template; /** * Class responsible for invoking all documentation generators. diff --git a/doc/src/main/java/com/gentics/mesh/generator/ExampleGeneratorRunner.java b/doc/src/main/java/com/gentics/mesh/generator/ExampleGeneratorRunner.java index 73cf23eaed..9050b015a1 100644 --- a/doc/src/main/java/com/gentics/mesh/generator/ExampleGeneratorRunner.java +++ b/doc/src/main/java/com/gentics/mesh/generator/ExampleGeneratorRunner.java @@ -6,6 +6,8 @@ import java.io.File; import java.io.IOException; +import com.gentics.mesh.generator.runner.OpenAPISpecGeneratorRunner; + /** * Runner for various example generators. */ @@ -49,6 +51,9 @@ public static void main(String[] args) throws Exception { }, true); ramlGenerator.run(); + // Generate OpenAPI base spec + OpenAPISpecGeneratorRunner.main(new String[] { OUTPUT_ROOT_FOLDER.getPath() }); + // Generate elasticsearch flattened models SearchModelGenerator searchModelGen = new SearchModelGenerator(OUTPUT_ROOT_FOLDER); searchModelGen.run(); diff --git a/mdm/api/pom.xml b/mdm/api/pom.xml index a528f0270e..0c7990b128 100644 --- a/mdm/api/pom.xml +++ b/mdm/api/pom.xml @@ -28,5 +28,35 @@ com.gentics.graphqlfilter graphql-java-filter + + com.gentics + vertx-openapi + + + org.slf4j + slf4j-parent + + + org.slf4j + slf4j-log4j12 + + + org.slf4j + slf4j-api + + + commons-validator + commons-validator + + + com.github.fge + json-schema-validator + + + com.fasterxml.jackson.module + jackson-module-jsonSchema + + + diff --git a/mdm/api/src/main/java/com/gentics/mesh/core/data/dao/JobDao.java b/mdm/api/src/main/java/com/gentics/mesh/core/data/dao/JobDao.java index d0a2b0417d..c39d30f08e 100644 --- a/mdm/api/src/main/java/com/gentics/mesh/core/data/dao/JobDao.java +++ b/mdm/api/src/main/java/com/gentics/mesh/core/data/dao/JobDao.java @@ -103,7 +103,6 @@ default Page findAllNoPerm(InternalActionContext ac, PagingPar * Delete the job. * * @param job - * @param bac */ void delete(HibJob job); diff --git a/mdm/api/src/main/java/com/gentics/mesh/parameter/AbstractParameters.java b/mdm/api/src/main/java/com/gentics/mesh/parameter/AbstractParameters.java index 4a18a516e4..e040590f9c 100644 --- a/mdm/api/src/main/java/com/gentics/mesh/parameter/AbstractParameters.java +++ b/mdm/api/src/main/java/com/gentics/mesh/parameter/AbstractParameters.java @@ -1,19 +1,20 @@ package com.gentics.mesh.parameter; +import java.util.Map; + +import org.raml.model.parameter.QueryParameter; + import com.gentics.mesh.doc.GenerateDocumentation; import com.gentics.mesh.handler.ActionContext; +import com.gentics.vertx.openapi.model.parameters.SimpleParameterProviderImpl; import io.vertx.core.MultiMap; -import java.util.Map; - -import static com.gentics.mesh.util.HttpQueryUtils.toMap; - /** * Abstract class for parameter provider implementations. */ @GenerateDocumentation -public abstract class AbstractParameters implements ParameterProvider { +public abstract class AbstractParameters extends SimpleParameterProviderImpl { protected MultiMap parameters; @@ -23,38 +24,25 @@ public AbstractParameters(ActionContext ac) { } public AbstractParameters(MultiMap parameters) { - this.parameters = parameters; + super(parameters); } public AbstractParameters() { this(MultiMap.caseInsensitiveMultiMap()); } + /** + * Return the RAML parameters for this provider. + * + * @return + */ + @Override + public abstract Map getRAMLParameters(); + /** * Returns the human readable name of the parameters. * * @return */ public abstract String getName(); - - @Override - public String getParameter(String name) { - return parameters.get(name); - } - - @Override - public Map getParameters() { - return toMap(parameters); - } - - @Override - public void setParameter(String name, String value) { - parameters.set(name, value); - } - - @Override - public String toString() { - return getQueryParameters(); - } - } diff --git a/mdm/api/src/main/java/com/gentics/mesh/parameter/ParameterProviderContext.java b/mdm/api/src/main/java/com/gentics/mesh/parameter/ParameterProviderContext.java index dea6134b71..8d3eb22159 100644 --- a/mdm/api/src/main/java/com/gentics/mesh/parameter/ParameterProviderContext.java +++ b/mdm/api/src/main/java/com/gentics/mesh/parameter/ParameterProviderContext.java @@ -2,15 +2,18 @@ import com.gentics.mesh.handler.ActionContext; import com.gentics.mesh.parameter.impl.BackupParametersImpl; +import com.gentics.mesh.parameter.impl.BinaryCheckParametersImpl; import com.gentics.mesh.parameter.impl.BranchParametersImpl; import com.gentics.mesh.parameter.impl.ConsistencyCheckParametersImpl; import com.gentics.mesh.parameter.impl.DeleteParametersImpl; import com.gentics.mesh.parameter.impl.DisplayParametersImpl; +import com.gentics.mesh.parameter.impl.EtagParametersImpl; import com.gentics.mesh.parameter.impl.GenericParametersImpl; import com.gentics.mesh.parameter.impl.ImageManipulationParametersImpl; import com.gentics.mesh.parameter.impl.ImageManipulationRetrievalParametersImpl; import com.gentics.mesh.parameter.impl.IndexMaintenanceParametersImpl; import com.gentics.mesh.parameter.impl.JobParametersImpl; +import com.gentics.mesh.parameter.impl.LanguageParametersImpl; import com.gentics.mesh.parameter.impl.NodeParametersImpl; import com.gentics.mesh.parameter.impl.PagingParametersImpl; import com.gentics.mesh.parameter.impl.ProjectLoadParametersImpl; @@ -44,6 +47,10 @@ default VersioningParameters getVersioningParameters() { return new VersioningParametersImpl(this); } + default LanguageParameters getLanguageParameters() { + return new LanguageParametersImpl(this); + } + default PagingParameters getPagingParameters() { return new PagingParametersImpl(this); } @@ -80,6 +87,10 @@ default GenericParameters getGenericParameters() { return new GenericParametersImpl(this); } + default EtagParameters getEtagParameters() { + return new EtagParametersImpl(this); + } + default ImageManipulationRetrievalParameters getImageManipulationRetrievalParameters() { return new ImageManipulationRetrievalParametersImpl(this); } @@ -111,4 +122,8 @@ default DisplayParameters getDisplayParameters() { default ConsistencyCheckParameters getConsistencyCheckParameters() { return new ConsistencyCheckParametersImpl(this); } + + default BinaryCheckParameters getBinaryCheckParameters() { + return new BinaryCheckParametersImpl(this); + } } diff --git a/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/BinaryCheckParametersImpl.java b/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/BinaryCheckParametersImpl.java new file mode 100644 index 0000000000..eaf18e9657 --- /dev/null +++ b/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/BinaryCheckParametersImpl.java @@ -0,0 +1,46 @@ +package com.gentics.mesh.parameter.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.raml.model.ParamType; +import org.raml.model.parameter.QueryParameter; + +import com.gentics.mesh.handler.ActionContext; +import com.gentics.mesh.parameter.AbstractParameters; +import com.gentics.mesh.parameter.BinaryCheckParameters; + +public class BinaryCheckParametersImpl extends AbstractParameters implements BinaryCheckParameters { + + public BinaryCheckParametersImpl(ActionContext ac) { + super(ac); + } + + public BinaryCheckParametersImpl() { + super(); + } + + @Override + public void validate() { + + } + + @Override + public Map getRAMLParameters() { + Map parameters = new HashMap<>(); + + QueryParameter langParameter = new QueryParameter(); + langParameter.setDescription("."); + langParameter.setExample("lhdgfsgfvaoyegfy"); + langParameter.setRequired(true); + langParameter.setType(ParamType.STRING); + parameters.put(SECRET_PARAMETER_KEY, langParameter); + + return parameters; + } + + @Override + public String getName() { + return "Binary check parameters"; + } +} diff --git a/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/EtagParametersImpl.java b/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/EtagParametersImpl.java new file mode 100644 index 0000000000..c84c4552b8 --- /dev/null +++ b/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/EtagParametersImpl.java @@ -0,0 +1,43 @@ +package com.gentics.mesh.parameter.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.raml.model.ParamType; +import org.raml.model.parameter.QueryParameter; + +import com.gentics.mesh.handler.ActionContext; +import com.gentics.mesh.parameter.AbstractParameters; +import com.gentics.mesh.parameter.EtagParameters; + +/** + * @see EtagParameters + */ +public class EtagParametersImpl extends AbstractParameters implements EtagParameters { + + public EtagParametersImpl(ActionContext ac) { + super(ac); + } + + public EtagParametersImpl() { + } + + @Override + public String getName() { + return "ETAG REST query parameters"; + } + + @Override + public Map getRAMLParameters() { + Map parameters = new HashMap<>(); + + QueryParameter etagParam = new QueryParameter(); + etagParam.setDescription( + "Parameter which can be used to disable the etag parameter generation and thus increase performance when etags are not needed."); + etagParam.setType(ParamType.BOOLEAN); + etagParam.setDefaultValue("true"); + parameters.put(ETAG_PARAM_KEY, etagParam); + + return parameters; + } +} diff --git a/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/GenericParametersImpl.java b/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/GenericParametersImpl.java index 14dd643be6..80bf255abb 100644 --- a/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/GenericParametersImpl.java +++ b/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/GenericParametersImpl.java @@ -7,13 +7,12 @@ import org.raml.model.parameter.QueryParameter; import com.gentics.mesh.handler.ActionContext; -import com.gentics.mesh.parameter.AbstractParameters; import com.gentics.mesh.parameter.GenericParameters; /** * @see GenericParameters */ -public class GenericParametersImpl extends AbstractParameters implements GenericParameters { +public class GenericParametersImpl extends EtagParametersImpl implements GenericParameters { public GenericParametersImpl(ActionContext ac) { super(ac); @@ -35,21 +34,15 @@ public String getName() { @Override public Map getRAMLParameters() { - Map parameters = new HashMap<>(); + Map parameters = new HashMap<>(super.getRAMLParameters()); QueryParameter fieldsParam = new QueryParameter(); fieldsParam.setDescription("Limit the output to certain fields. This is useful in order to reduce the response JSON overhead."); fieldsParam.setType(ParamType.STRING); fieldsParam.setDefaultValue(""); + fieldsParam.setExample("uuid,name"); parameters.put(FIELDS_PARAM_KEY, fieldsParam); - QueryParameter etagParam = new QueryParameter(); - etagParam.setDescription( - "Parameter which can be used to disable the etag parameter generation and thus increase performance when etags are not needed."); - etagParam.setType(ParamType.BOOLEAN); - etagParam.setDefaultValue("true"); - parameters.put(ETAG_PARAM_KEY, etagParam); - return parameters; } diff --git a/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/JobParametersImpl.java b/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/JobParametersImpl.java index fb9e361bf5..e90b0bccaf 100644 --- a/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/JobParametersImpl.java +++ b/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/JobParametersImpl.java @@ -1,11 +1,15 @@ package com.gentics.mesh.parameter.impl; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import org.apache.commons.lang3.ArrayUtils; import org.raml.model.ParamType; import org.raml.model.parameter.QueryParameter; +import com.gentics.mesh.core.rest.job.JobStatus; +import com.gentics.mesh.core.rest.job.JobType; import com.gentics.mesh.handler.ActionContext; import com.gentics.mesh.parameter.AbstractParameters; import com.gentics.mesh.parameter.JobParameters; @@ -34,9 +38,9 @@ public JobParametersImpl(ActionContext ac) { Map parameters = new HashMap<>(); parameters.put(STATUS_PARAMETER_KEY, createQueryParameter( - "Parameter for filtering jobs by their status. Multiple values can be given separated by commas.")); + "Parameter for filtering jobs by their status. Multiple values can be given separated by commas.", ArrayUtils.toStringArray(JobStatus.values()))); parameters.put(TYPE_PARAMETER_KEY, createQueryParameter( - "Parameter for filtering jobs by their type. Multiple values can be given separated by commas.")); + "Parameter for filtering jobs by their type. Multiple values can be given separated by commas.", ArrayUtils.toStringArray(JobType.values()))); parameters.put(BRANCH_NAME_PARAMETER_KEY, createQueryParameter( "Parameter for filtering jobs by the branch name. Multiple values can be given separated by commas.")); parameters.put(BRANCH_UUID_PARAMETER_KEY, createQueryParameter( @@ -67,11 +71,15 @@ public String getName() { * @param description parameter description * @return query parameter */ - protected QueryParameter createQueryParameter(String description) { + protected QueryParameter createQueryParameter(String description, String... enumValues) { QueryParameter param = new QueryParameter(); param.setDescription(description); param.setType(ParamType.STRING); - param.setDefaultValue(""); + if (enumValues.length > 0) { + param.setEnumeration(Arrays.asList(enumValues)); + } else { + param.setDefaultValue(""); + } return param; } } \ No newline at end of file diff --git a/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/LanguageParametersImpl.java b/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/LanguageParametersImpl.java new file mode 100644 index 0000000000..a76b703526 --- /dev/null +++ b/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/LanguageParametersImpl.java @@ -0,0 +1,42 @@ +package com.gentics.mesh.parameter.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.raml.model.ParamType; +import org.raml.model.parameter.QueryParameter; + +import com.gentics.mesh.handler.ActionContext; +import com.gentics.mesh.parameter.AbstractParameters; + +public class LanguageParametersImpl extends AbstractParameters implements com.gentics.mesh.parameter.LanguageParameters { + + public LanguageParametersImpl(ActionContext ac) { + super(ac); + } + + public LanguageParametersImpl() { + super(); + } + + @Override + public Map getRAMLParameters() { + Map parameters = new HashMap<>(); + + // lang + QueryParameter langParameter = new QueryParameter(); + langParameter.setDescription( + "ISO 639-1 language tag of the language which should be loaded. Fallback handling can be applied by specifying multiple languages in a comma-separated list. The first matching language will be returned. If omitted or the requested language is not available then the _defaultLanguage_ as configured in _mesh.yml_ will be returned."); + langParameter.setExample("en,de"); + langParameter.setRequired(false); + langParameter.setType(ParamType.STRING); + parameters.put(LANGUAGES_QUERY_PARAM_KEY, langParameter); + + return parameters; + } + + @Override + public String getName() { + return "Language parameters"; + } +} diff --git a/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/NodeParametersImpl.java b/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/NodeParametersImpl.java index 990d508c8b..d4609333d2 100644 --- a/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/NodeParametersImpl.java +++ b/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/NodeParametersImpl.java @@ -1,19 +1,21 @@ package com.gentics.mesh.parameter.impl; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.stream.Collectors; import org.raml.model.ParamType; import org.raml.model.parameter.QueryParameter; import com.gentics.mesh.handler.ActionContext; -import com.gentics.mesh.parameter.AbstractParameters; +import com.gentics.mesh.parameter.LinkType; import com.gentics.mesh.parameter.NodeParameters; /** * @see NodeParameters */ -public class NodeParametersImpl extends AbstractParameters implements NodeParameters { +public class NodeParametersImpl extends LanguageParametersImpl implements NodeParameters { public NodeParametersImpl(ActionContext ac) { super(ac); @@ -35,16 +37,7 @@ public String getName() { @Override public Map getRAMLParameters() { - Map parameters = new HashMap<>(); - - // lang - QueryParameter langParameter = new QueryParameter(); - langParameter.setDescription( - "ISO 639-1 language tag of the language which should be loaded. Fallback handling can be applied by specifying multiple languages in a comma-separated list. The first matching language will be returned. If omitted or the requested language is not available then the _defaultLanguage_ as configured in _mesh.yml_ will be returned."); - langParameter.setExample("en,de"); - langParameter.setRequired(false); - langParameter.setType(ParamType.STRING); - parameters.put(LANGUAGES_QUERY_PARAM_KEY, langParameter); + Map parameters = new HashMap<>(super.getRAMLParameters()); // resolveLinks QueryParameter resolveLinksParameter = new QueryParameter(); @@ -53,6 +46,7 @@ public String getName() { resolveLinksParameter.setExample("medium"); resolveLinksParameter.setRequired(false); resolveLinksParameter.setType(ParamType.STRING); + resolveLinksParameter.setEnumeration(Arrays.asList(LinkType.values()).stream().map(e -> e.name().toLowerCase()).collect(Collectors.toList())); parameters.put(RESOLVE_LINKS_QUERY_PARAM_KEY, resolveLinksParameter); return parameters; diff --git a/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/SortingParametersImpl.java b/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/SortingParametersImpl.java index 17805f4b71..7e85bae2d6 100644 --- a/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/SortingParametersImpl.java +++ b/mdm/api/src/main/java/com/gentics/mesh/parameter/impl/SortingParametersImpl.java @@ -3,6 +3,7 @@ import static com.gentics.mesh.core.rest.error.Errors.error; import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST; +import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -56,11 +57,11 @@ public SortingParametersImpl(ActionContext ac) { // sort order QueryParameter sortOrderParameter = new QueryParameter(); - sortOrderParameter.setDescription("Field order (ASC/DESC/UNSORTED) to sort the result by."); - sortOrderParameter.setDefaultValue(SortingParameters.DEFAULT_SORT_ORDER.name()); + sortOrderParameter.setDescription("Field order (ASC/DESC) to sort the result by."); sortOrderParameter.setExample(SortOrder.ASCENDING.name()); sortOrderParameter.setRequired(false); sortOrderParameter.setType(ParamType.STRING); + sortOrderParameter.setEnumeration(Arrays.asList(SortOrder.values()).stream().filter(e -> SortOrder.UNSORTED != e).map(e -> e.getValue().toLowerCase()).collect(Collectors.toList())); parameters.put(SortingParameters.SORT_ORDER_PARAMETER_KEY, sortOrderParameter); return parameters; diff --git a/mdm/api/src/main/java/com/gentics/mesh/rest/InternalEndpointRoute.java b/mdm/api/src/main/java/com/gentics/mesh/rest/InternalEndpointRoute.java index 83a476a641..3cdd4a3607 100644 --- a/mdm/api/src/main/java/com/gentics/mesh/rest/InternalEndpointRoute.java +++ b/mdm/api/src/main/java/com/gentics/mesh/rest/InternalEndpointRoute.java @@ -1,404 +1,14 @@ package com.gentics.mesh.rest; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import io.vertx.ext.web.Router; -import org.codehaus.jettison.json.JSONObject; -import org.raml.model.MimeType; -import org.raml.model.Response; -import org.raml.model.parameter.FormParameter; -import org.raml.model.parameter.QueryParameter; -import org.raml.model.parameter.UriParameter; - import com.gentics.mesh.core.rest.MeshEvent; -import com.gentics.mesh.core.rest.admin.localconfig.LocalConfigModel; -import com.gentics.mesh.core.rest.common.RestModel; -import com.gentics.mesh.parameter.ParameterProvider; -import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.Handler; -import io.vertx.core.http.HttpMethod; -import io.vertx.ext.web.Route; import io.vertx.ext.web.RoutingContext; /** * Simple wrapper for vert.x routes. The wrapper is commonly used to generate RAML descriptions for the route. */ -public interface InternalEndpointRoute extends Comparable { - - /** - * Wrapper for {@link Route#path(String)}. - * - * @param path - * @return Fluent API - */ - InternalEndpointRoute path(String path); - - /** - * Set the http method of the endpoint. - * - * @param method - * @return Fluent API - */ - InternalEndpointRoute method(HttpMethod method); - - /** - * Add a content type consumed by this endpoint. Used for content based routing. - * - * @param contentType - * the content type - * @return Fluent API - */ - InternalEndpointRoute consumes(String contentType); - - /** - * Set the request handler for the endpoint. - * - * @param requestHandler - * @return Fluent API - */ - InternalEndpointRoute handler(Handler requestHandler); - - /** - * Create a sub router - * @param router - * @return - */ - InternalEndpointRoute subRouter(Router router); - - /** - * Wrapper for {@link Route#last()} - * - * @return Fluent API - */ - InternalEndpointRoute last(); - - /** - * Wrapper for {@link Route#order(int)} - * - * @param order - * @return Fluent API - */ - InternalEndpointRoute order(int order); - - /** - * Validate that all mandatory fields have been set. - * - * @return Fluent API - */ - InternalEndpointRoute validate(); - - /** - * Wrapper for {@link Route#remove()} - * - * @return Fluent API - */ - InternalEndpointRoute remove(); - - /** - * Wrapper for {@link Route#disable()} - * - * @return Fluent API - */ - InternalEndpointRoute disable(); - - /** - * Wrapper for {@link Route#enable()} - * - * @return Fluent API - */ - InternalEndpointRoute enable(); - - /** - * Wrapper for {@link Route#useNormalisedPath(boolean)}. - * - * @param useNormalisedPath - * @return - */ - InternalEndpointRoute useNormalisedPath(boolean useNormalisedPath); - - /** - * Wrapper for {@link Route#getPath()} - * - * @return the path prefix (if any) for this route - */ - String getPath(); - - /** - * Return the endpoint description. - * - * @return Endpoint description - */ - String getDescription(); - - /** - * Return the display name for the endpoint. - * - * @return Endpoint display name - */ - String getDisplayName(); - - /** - * Add the given response to the example responses. - * - * @param status - * Status code of the response - * @param description - * Description of the response - * @return Fluent API - */ - InternalEndpointRoute exampleResponse(HttpResponseStatus status, String description); - - /** - * Add the given response to the example responses. - * - * @param status - * Status code for the example response - * @param model - * Model which will be turned into JSON - * @param description - * Description of the example response - * @return Fluent API - */ - InternalEndpointRoute exampleResponse(HttpResponseStatus status, Object model, String description); - - /** - * Add the given response to the example responses. - * - * @param status - * Status code of the example response - * @param description - * Description of the example - * @param headerName - * Name of the header value - * @param example - * Example header value - * @param headerDescription - * Description of the header - * @return - */ - InternalEndpointRoute exampleResponse(HttpResponseStatus status, String description, String headerName, String example, String headerDescription); - - /** - * Create a blocking handler for the endpoint. - * The handler will be created "ordered", which means that handlers will not be called concurrently. - * This should only be used, when absolutely necessary and only for mutating requests. - * In all other cases, {@link #blockingHandler(Handler, boolean)} with ordered: false should be used. - * - * @param requestHandler request handler - * @return Fluent API - * @deprecated since requests will only be "ordered" when running in the same http verticle - */ - InternalEndpointRoute blockingHandler(Handler requestHandler); - - /** - * Create a blocking handler for the endpoint. - * - * @param requestHandler request handler - * @param ordered if the handlers should be called in order or may be called concurrently - * @return Fluent API - */ - InternalEndpointRoute blockingHandler(Handler requestHandler, boolean ordered); - - /** - * Create a failure handler for the endpoint. - * - * @param failureHandler - * @return Fluent API - */ - InternalEndpointRoute failureHandler(Handler failureHandler); - - /** - * Parse the RAML path and return a list of all segment name variables. - * - * @return List of path segments - */ - List getNamedSegments(); - - /** - * Set the content type for elements which are returned by the endpoint. - * - * @param contentType - * @return Fluent API - */ - InternalEndpointRoute produces(String contentType); - - /** - * Set the path using a regex. - * - * @param path - * @return Fluent API - */ - InternalEndpointRoute pathRegex(String path); - - /** - * Return the path used for RAML. If non null the path which was previously set using {@link #setRAMLPath(String)} will be returned. Otherwise the converted - * vert.x route path is returned. A vert.x path /:nodeUuid is converted to a RAML path /{nodeUuid}. - * - * @return RAML path - */ - String getRamlPath(); - - /** - * Set the endpoint display name. - * - * @param name - * @return Fluent API - */ - InternalEndpointRoute displayName(String name); - - /** - * Set the endpoint description. - * - * @param description - * Description of the endpoint. - * @return Fluent API - */ - InternalEndpointRoute description(String description); - - /** - * Add an uri parameter with description and example to the endpoint. - * - * @param key - * Key of the endpoint (e.g.: query, perPage) - * @param description - * @param example - * Example URI parameter value - */ - InternalEndpointRoute addUriParameter(String key, String description, String example); - - /** - * Return the uri parameters for the endpoint. - * - * @return Map with uri parameters - */ - Map getUriParameters(); - - /** - * Explicitly set the RAML path. This will override the path which is otherwise transformed using the vertx route path. - * - * @param path - */ - InternalEndpointRoute setRAMLPath(String path); - - /** - * - * @param name - * @param description - * @param example - * @return - */ - InternalEndpointRoute addQueryParameter(String name, String description, String example); - - /** - * Add a query parameter provider to the endpoint. The query parameter provider will in turn provide examples, descriptions for all query parameters which - * the parameter provider provides. - * - * @param clazz - * Class which provides the parameters - * @return Fluent API - */ - InternalEndpointRoute addQueryParameters(Class clazz); - - /** - * Return the list of query parameters for the endpoint. - * - * @return - */ - Map getQueryParameters(); - - /** - * Return the Vert.x route path regex. - * - * @return configured path regex or null if no path regex has been set - */ - String getPathRegex(); - - /** - * Return the endpoint HTTP example request map. - * - * @return - */ - HashMap getExampleRequestMap(); - - /** - * Return the map of example responses. The map contains examples per http status code. - * - * @return - */ - Map getExampleResponses(); - - /** - * Return the method used for the endpoint. - * - * @return - */ - HttpMethod getMethod(); - - /** - * Return the traits which were set for this endpoint. - * - * @return - */ - String[] getTraits(); - - /** - * Set the traits information. - * - * @param traits - * Traits which the endpoint should inherit - * @return Fluent API - */ - InternalEndpointRoute traits(String... traits); - - /** - * Set the endpoint json example request via the provided json object. The JSON schema will not be generated. - * - * @param jsonObject - * @return Fluent API - */ - InternalEndpointRoute exampleRequest(JSONObject jsonObject); - - /** - * Set the endpoint example request via a JSON example model. The json schema will automatically be generated. - * - * @param model - * Example Rest Model - * @return Fluent API - */ - InternalEndpointRoute exampleRequest(RestModel model); - - /** - * Set the endpoint request example via a form parameter list. - * - * @param parameters - * @return Fluent API - */ - InternalEndpointRoute exampleRequest(Map> parameters); - - /** - * Set the endpoint request example via a plain text body. - * - * @param bodyText - * @return Fluent API - */ - InternalEndpointRoute exampleRequest(String bodyText); - - /** - * Return map with status code and the response class. - * - * @return - */ - Map> getExampleResponseClasses(); - - /** - * Return the rest model class for the example request. - * - * @return - */ - Class getExampleRequestClass(); +public interface InternalEndpointRoute extends com.gentics.vertx.openapi.metadata.InternalEndpointRoute { /** * Set the events which are emitted by the action of the endpoint. @@ -409,33 +19,26 @@ public interface InternalEndpointRoute extends Comparable InternalEndpointRoute events(MeshEvent... events); /** - * If true, this endpoint will create, update or delete items in the database. - * The route will throw an error if this instance is in read only mode. - * - * Per default, all POST, DELETE and PUT requests are mutating, other requests are not. + * @see com.gentics.vertx.openapi.metadata.InternalEndpointRoute#blockingHandler(Handler) * - * @see LocalConfigModel#isReadOnly() - * @return + * @deprecated since requests will only be "ordered" when running in the same http verticle */ - boolean isMutating(); + @Override + @Deprecated + InternalEndpointRoute blockingHandler(Handler requestHandler); /** - * If true, this endpoint will create, update or delete items in the database. - * The route will throw an error if this instance is in read only mode. - * - * Per default, all POST, DELETE and PUT requests are mutating, other requests are not. - * - * @see LocalConfigModel#isReadOnly() - * @param mutating + * If true, the endpoint can be used with no authentication. + * * @return */ - InternalEndpointRoute setMutating(Boolean mutating); + boolean isInsecure(); /** - * Return underlying route. + * Set the endpoint to omit the secure token requirement. * + * @param insecure * @return */ - Route getRoute(); - + InternalEndpointRoute setInsecure(boolean insecure); } diff --git a/mdm/api/src/main/java/com/gentics/mesh/router/APIRouter.java b/mdm/api/src/main/java/com/gentics/mesh/router/APIRouter.java index 12448d80e9..60a57be4cd 100644 --- a/mdm/api/src/main/java/com/gentics/mesh/router/APIRouter.java +++ b/mdm/api/src/main/java/com/gentics/mesh/router/APIRouter.java @@ -5,14 +5,7 @@ /** * Central router for /api/v1 routes */ -public interface APIRouter { - - /** - * Internal vert.x router for the API router. - * - * @return - */ - Router getRouter(); +public interface APIRouter extends InternalRouter { /** * Return the router to which all projects will be mounted. diff --git a/mdm/api/src/main/java/com/gentics/mesh/router/CustomRouter.java b/mdm/api/src/main/java/com/gentics/mesh/router/CustomRouter.java index 538169e3dc..35151892a6 100644 --- a/mdm/api/src/main/java/com/gentics/mesh/router/CustomRouter.java +++ b/mdm/api/src/main/java/com/gentics/mesh/router/CustomRouter.java @@ -3,6 +3,6 @@ /** * Marker interface for custom routers. */ -public interface CustomRouter { +public interface CustomRouter extends InternalRouter { } diff --git a/mdm/api/src/main/java/com/gentics/mesh/router/InternalRouter.java b/mdm/api/src/main/java/com/gentics/mesh/router/InternalRouter.java new file mode 100644 index 0000000000..8225ad9486 --- /dev/null +++ b/mdm/api/src/main/java/com/gentics/mesh/router/InternalRouter.java @@ -0,0 +1,16 @@ +package com.gentics.mesh.router; + +import io.vertx.ext.web.Router; + +/** + * A base for all internal routers + */ +public interface InternalRouter { + + /** + * Internal vert.x router for the API router. + * + * @return + */ + Router getRouter(); +} diff --git a/mdm/api/src/main/java/com/gentics/mesh/router/PluginRouter.java b/mdm/api/src/main/java/com/gentics/mesh/router/PluginRouter.java index 1657e5e2cb..6d228adbdd 100644 --- a/mdm/api/src/main/java/com/gentics/mesh/router/PluginRouter.java +++ b/mdm/api/src/main/java/com/gentics/mesh/router/PluginRouter.java @@ -1,11 +1,13 @@ package com.gentics.mesh.router; +import java.util.Map; + import io.vertx.ext.web.Router; /** * Router to track plugin sub routers. */ -public interface PluginRouter { +public interface PluginRouter extends InternalRouter { /** * Remove the plugin router. @@ -22,4 +24,10 @@ public interface PluginRouter { */ void addRouter(String name, Router pluginRouter); + /** + * Get currently registered routers. + * + * @return immutable name/router map + */ + Map pluginRouters(); } diff --git a/mdm/api/src/main/java/com/gentics/mesh/router/ProjectRouter.java b/mdm/api/src/main/java/com/gentics/mesh/router/ProjectRouter.java index 7f4abbd90f..aa14048040 100644 --- a/mdm/api/src/main/java/com/gentics/mesh/router/ProjectRouter.java +++ b/mdm/api/src/main/java/com/gentics/mesh/router/ProjectRouter.java @@ -7,14 +7,7 @@ /** * This class manages the project routers (e.g. routers for endpoints like :apibase:/:projectName/nodes) */ -public interface ProjectRouter { - - /** - * Return the Vert.x router. - * - * @return - */ - Router getRouter(); +public interface ProjectRouter extends InternalRouter { /** * Return all routers that have been registered. diff --git a/mdm/api/src/main/java/com/gentics/mesh/router/ProjectsRouter.java b/mdm/api/src/main/java/com/gentics/mesh/router/ProjectsRouter.java index c12a9ca330..a78a6fa52e 100644 --- a/mdm/api/src/main/java/com/gentics/mesh/router/ProjectsRouter.java +++ b/mdm/api/src/main/java/com/gentics/mesh/router/ProjectsRouter.java @@ -6,7 +6,7 @@ import io.vertx.ext.web.Router; -public interface ProjectsRouter { +public interface ProjectsRouter extends InternalRouter { /** * Common router which holds project specific routes (e.g: /nodes /tagFamilies) diff --git a/mdm/api/src/main/java/com/gentics/mesh/router/RootRouter.java b/mdm/api/src/main/java/com/gentics/mesh/router/RootRouter.java index ea72c30611..52f91c9202 100644 --- a/mdm/api/src/main/java/com/gentics/mesh/router/RootRouter.java +++ b/mdm/api/src/main/java/com/gentics/mesh/router/RootRouter.java @@ -1,11 +1,9 @@ package com.gentics.mesh.router; -import io.vertx.ext.web.Router; - /** * The root router is the top level router of the routing stack. */ -public interface RootRouter { +public interface RootRouter extends InternalRouter { /** * Return the /api/v1 router @@ -14,13 +12,6 @@ public interface RootRouter { */ APIRouter apiRouter(); - /** - * Return the Vert.x router. - * - * @return - */ - Router getRouter(); - /** * Return the central router storage. * diff --git a/mdm/common/src/main/java/com/gentics/mesh/example/MiscExamples.java b/mdm/common/src/main/java/com/gentics/mesh/example/MiscExamples.java index 1155d66e77..405e53a27a 100644 --- a/mdm/common/src/main/java/com/gentics/mesh/example/MiscExamples.java +++ b/mdm/common/src/main/java/com/gentics/mesh/example/MiscExamples.java @@ -4,10 +4,8 @@ import java.util.Map; import java.util.stream.Stream; -import org.codehaus.jettison.json.JSONException; -import org.codehaus.jettison.json.JSONObject; - import com.gentics.mesh.core.rest.auth.LoginRequest; +import com.gentics.mesh.core.rest.auth.TokenResponse; import com.gentics.mesh.core.rest.common.GenericMessageResponse; import com.gentics.mesh.core.rest.search.EntityMetrics; import com.gentics.mesh.core.rest.search.SearchStatusResponse; @@ -62,29 +60,20 @@ public GenericMessageResponse createMessageResponse() { return message; } - public JSONObject getSearchQueryExample() { - JSONObject node = new JSONObject(); - try { - JSONObject query = new JSONObject(); - JSONObject queryString = new JSONObject(); - queryString.put("query", "some name"); - query.put("query_string", queryString); - node.put("query", query); - } catch (JSONException e) { - e.printStackTrace(); - } + public JsonObject getSearchQueryExample() { + JsonObject node = new JsonObject(); + JsonObject query = new JsonObject(); + JsonObject queryString = new JsonObject(); + queryString.put("query", "some name"); + query.put("query_string", queryString); + node.put("query", query); return node; } - public JSONObject getAuthTokenResponse() { - JSONObject node = new JSONObject(); - try { - node.put("token", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyVXVpZCI6IlVVSURPRlVTRVIxIiwiZXhwIjoxNDY5MTE3MjQ3LCJpYXQiOjE0NjkxMTM2NDd9.i1u4RMs4K7zBkGhmcpp1P79Wpz2UQYJkZKJTVdFp_iU="); - } catch (JSONException e) { - e.printStackTrace(); - } - return node; + public TokenResponse getAuthTokenResponse() { + TokenResponse response = new TokenResponse(); + response.setToken("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyVXVpZCI6IlVVSURPRlVTRVIxIiwiZXhwIjoxNDY5MTE3MjQ3LCJpYXQiOjE0NjkxMTM2NDd9.i1u4RMs4K7zBkGhmcpp1P79Wpz2UQYJkZKJTVdFp_iU="); + return response; } public JsonObject createSearchResponse() { diff --git a/mdm/common/src/main/java/com/gentics/mesh/example/NodeExamples.java b/mdm/common/src/main/java/com/gentics/mesh/example/NodeExamples.java index 241bb0bca7..c34b7fc27e 100644 --- a/mdm/common/src/main/java/com/gentics/mesh/example/NodeExamples.java +++ b/mdm/common/src/main/java/com/gentics/mesh/example/NodeExamples.java @@ -40,6 +40,7 @@ import com.gentics.mesh.MeshVersion; import com.gentics.mesh.core.rest.navigation.NavigationElement; import com.gentics.mesh.core.rest.navigation.NavigationResponse; +import com.gentics.mesh.core.rest.node.BinaryCheckUpdateRequest; import com.gentics.mesh.core.rest.node.FieldMap; import com.gentics.mesh.core.rest.node.FieldMapImpl; import com.gentics.mesh.core.rest.node.NodeChildrenInfo; @@ -48,6 +49,7 @@ import com.gentics.mesh.core.rest.node.NodeResponse; import com.gentics.mesh.core.rest.node.NodeUpdateRequest; import com.gentics.mesh.core.rest.node.PublishStatusModel; +import com.gentics.mesh.core.rest.node.field.BinaryCheckStatus; import com.gentics.mesh.core.rest.node.field.BinaryField; import com.gentics.mesh.core.rest.node.field.BinaryFieldTransformRequest; import com.gentics.mesh.core.rest.node.field.Field; @@ -60,6 +62,7 @@ import com.gentics.mesh.core.rest.node.field.impl.HtmlFieldImpl; import com.gentics.mesh.core.rest.node.field.impl.NumberFieldImpl; import com.gentics.mesh.core.rest.node.field.impl.StringFieldImpl; +import com.gentics.mesh.core.rest.node.field.s3binary.S3BinaryUploadRequest; import com.gentics.mesh.core.rest.node.version.NodeVersionsResponse; import com.gentics.mesh.core.rest.node.version.VersionInfo; import com.gentics.mesh.core.rest.schema.impl.SchemaReferenceImpl; @@ -334,22 +337,18 @@ public Map> getExampleBinaryUploadFormParameters() { return parameters; } - public Map> getExampleBinaryCheckCallbackParameters() { - Map> parameters = new HashMap<>(); - FormParameter statusParameter = new FormParameter(); - statusParameter.setExample("DENIED"); - statusParameter.setType(ParamType.STRING); - statusParameter.setDescription("The result of the binary check. One of ACCEPTED or DENIED."); - statusParameter.setRequired(true); - parameters.put("status", Arrays.asList(statusParameter)); - - FormParameter reasonParameter = new FormParameter(); - reasonParameter.setExample("Malware detected"); - reasonParameter.setType(ParamType.STRING); - reasonParameter.setDescription("The reason why the binary was denied."); - reasonParameter.setRequired(false); - parameters.put("reason", Arrays.asList(reasonParameter)); + public S3BinaryUploadRequest getExampleS3BinaryUploadFormParameters() { + S3BinaryUploadRequest parameters = new S3BinaryUploadRequest(); + parameters.setVersion("1.0"); + parameters.setLanguage("en"); + parameters.setFilename("blumen/blume.jpg"); + return parameters; + } + public BinaryCheckUpdateRequest getExampleBinaryCheckCallbackParameters() { + BinaryCheckUpdateRequest parameters = new BinaryCheckUpdateRequest(); + parameters.setStatus(BinaryCheckStatus.DENIED); + parameters.setReason("Malware detected"); return parameters; } diff --git a/mdm/common/src/main/java/com/gentics/mesh/example/SchemaExamples.java b/mdm/common/src/main/java/com/gentics/mesh/example/SchemaExamples.java index 20b5b7e337..4a769e0fae 100644 --- a/mdm/common/src/main/java/com/gentics/mesh/example/SchemaExamples.java +++ b/mdm/common/src/main/java/com/gentics/mesh/example/SchemaExamples.java @@ -7,6 +7,7 @@ import static com.gentics.mesh.core.rest.schema.change.impl.SchemaChangeOperation.UPDATEFIELD; import static com.gentics.mesh.example.ExampleUuids.UUID_1; +import com.gentics.mesh.core.rest.common.GenericMessageResponse; import com.gentics.mesh.core.rest.schema.HtmlFieldSchema; import com.gentics.mesh.core.rest.schema.ListFieldSchema; import com.gentics.mesh.core.rest.schema.MicronodeFieldSchema; diff --git a/mdm/hibernate-api/src/main/java/com/gentics/mesh/etc/config/HibernateMeshOptions.java b/mdm/hibernate-api/src/main/java/com/gentics/mesh/etc/config/HibernateMeshOptions.java index 49e934b403..ab4bd05d07 100644 --- a/mdm/hibernate-api/src/main/java/com/gentics/mesh/etc/config/HibernateMeshOptions.java +++ b/mdm/hibernate-api/src/main/java/com/gentics/mesh/etc/config/HibernateMeshOptions.java @@ -123,4 +123,22 @@ public void setLicenseKeyPath(String licenseKeyPath) { public boolean hasDatabaseLevelCache() { return true; } + + @Override + @JsonIgnore + public Version getDefaultOpenAPIVersion() { + return Version.V30; + } + + @Override + @JsonIgnore + public Format getDefaultOpenAPIFormat() { + return Format.YAML; + } + + @Override + @JsonIgnore + public String getNoApiInfoPlugins() { + return null; + } } diff --git a/mdm/hibernate-core/src/main/java/com/gentics/mesh/dagger/AdminEndpointProviderModule.java b/mdm/hibernate-core/src/main/java/com/gentics/mesh/dagger/EndpointProviderModule.java similarity index 78% rename from mdm/hibernate-core/src/main/java/com/gentics/mesh/dagger/AdminEndpointProviderModule.java rename to mdm/hibernate-core/src/main/java/com/gentics/mesh/dagger/EndpointProviderModule.java index 974b472272..3fb64ab83f 100644 --- a/mdm/hibernate-core/src/main/java/com/gentics/mesh/dagger/AdminEndpointProviderModule.java +++ b/mdm/hibernate-core/src/main/java/com/gentics/mesh/dagger/EndpointProviderModule.java @@ -13,6 +13,7 @@ import com.gentics.mesh.core.endpoint.admin.JobHandler; import com.gentics.mesh.core.endpoint.admin.LocalConfigApi; import com.gentics.mesh.core.endpoint.admin.LocalConfigHandler; +import com.gentics.mesh.core.endpoint.admin.RestInfoEndpoint; import com.gentics.mesh.core.endpoint.admin.ShutdownHandler; import com.gentics.mesh.core.endpoint.admin.consistency.ConsistencyCheckHandler; import com.gentics.mesh.core.endpoint.admin.debuginfo.DebugInfoHandler; @@ -21,6 +22,7 @@ import com.gentics.mesh.core.verticle.handler.WriteLock; import com.gentics.mesh.distributed.coordinator.Coordinator; import com.gentics.mesh.endpoint.admin.HibAdminHandler; +import com.gentics.mesh.etc.config.HibernateMeshOptions; import com.gentics.mesh.etc.config.MeshOptions; import com.gentics.mesh.router.RouterStorageImpl; import com.gentics.mesh.router.RouterStorageRegistryImpl; @@ -31,7 +33,21 @@ import io.vertx.core.Vertx; @Module -public class AdminEndpointProviderModule { +public class EndpointProviderModule { + + @Provides + public static HibernateMeshOptions hibernateMeshOptions(MeshOptions meshOptions) { + if (meshOptions instanceof HibernateMeshOptions) { + return (HibernateMeshOptions) meshOptions; + } else { + throw new IllegalArgumentException("Unsupported MeshOptions class:" + meshOptions.getClass().getCanonicalName()); + } + } + + @Provides + public static RestInfoEndpoint provideRestInfoEndpoint(MeshAuthChain chain, AdminHandler adminHandler, LocalConfigApi localConfigApi, Database db, MeshOptions options) { + return new RestInfoEndpoint(chain, adminHandler, localConfigApi, db, options); + } @Provides public static AdminEndpoint provideAdminEndpoint(MeshAuthChain chain, AdminHandler adminHandler, JobHandler jobHandler, diff --git a/mdm/hibernate-core/src/main/java/com/gentics/mesh/dagger/HibernateMeshComponent.java b/mdm/hibernate-core/src/main/java/com/gentics/mesh/dagger/HibernateMeshComponent.java index bb25bc406e..98157a48b7 100644 --- a/mdm/hibernate-core/src/main/java/com/gentics/mesh/dagger/HibernateMeshComponent.java +++ b/mdm/hibernate-core/src/main/java/com/gentics/mesh/dagger/HibernateMeshComponent.java @@ -22,7 +22,7 @@ * Central dagger mesh component which will expose dependencies. */ @Singleton -@Component(modules = { CommonModule.class, HibernateModule.class, SearchWaitUtilProviderModule.class, AdminEndpointProviderModule.class, DatabaseConnectorModule.class, AuthChainProviderModule.class }) +@Component(modules = { CommonModule.class, HibernateModule.class, SearchWaitUtilProviderModule.class, EndpointProviderModule.class, DatabaseConnectorModule.class, AuthChainProviderModule.class }) public interface HibernateMeshComponent extends MeshComponent { @Getter diff --git a/mdm/hibernate-core/src/main/java/com/gentics/mesh/dagger/HibernateModule.java b/mdm/hibernate-core/src/main/java/com/gentics/mesh/dagger/HibernateModule.java index 785dd0e446..0a7f7b6913 100644 --- a/mdm/hibernate-core/src/main/java/com/gentics/mesh/dagger/HibernateModule.java +++ b/mdm/hibernate-core/src/main/java/com/gentics/mesh/dagger/HibernateModule.java @@ -93,8 +93,6 @@ import com.gentics.mesh.database.cluster.HibClusterManager; import com.gentics.mesh.distributed.MasterInfoProvider; import com.gentics.mesh.distributed.MasterInfoProviderImpl; -import com.gentics.mesh.etc.config.HibernateMeshOptions; -import com.gentics.mesh.etc.config.MeshOptions; import com.gentics.mesh.hibernate.HibernateRootResolver; import com.gentics.mesh.hibernate.data.binary.impl.HibBinariesImpl; import com.gentics.mesh.hibernate.data.dao.BinaryDaoImpl; @@ -292,15 +290,6 @@ public abstract class HibernateModule { @Binds abstract S3Binaries bindS3Binaries(S3HibBinariesImpl e); - @Provides - public static HibernateMeshOptions hibernateMeshOptions(MeshOptions meshOptions) { - if (meshOptions instanceof HibernateMeshOptions) { - return (HibernateMeshOptions) meshOptions; - } else { - throw new IllegalArgumentException("Unsupported MeshOptions class:" + meshOptions.getClass().getCanonicalName()); - } - } - @Provides @Singleton public static HazelcastInstance hazelcast(HibClusterManager clusterManager) { diff --git a/mdm/hibernate-core/src/main/java/com/gentics/mesh/database/cluster/HibClusterManager.java b/mdm/hibernate-core/src/main/java/com/gentics/mesh/database/cluster/HibClusterManager.java index be40844990..5fcdacc087 100644 --- a/mdm/hibernate-core/src/main/java/com/gentics/mesh/database/cluster/HibClusterManager.java +++ b/mdm/hibernate-core/src/main/java/com/gentics/mesh/database/cluster/HibClusterManager.java @@ -6,6 +6,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import javax.inject.Inject; @@ -57,7 +58,7 @@ public HazelcastInstance getHazelcast() { config = new Config(); } config.setInstanceName(options.getNodeName()); - config.setClusterName(options.getClusterOptions().getClusterName()); + config.setClusterName(Optional.ofNullable(options.getClusterOptions().getClusterName()).orElseGet(() -> options.getNodeName())); config.setClassLoader(Thread.currentThread().getContextClassLoader()); config.getMemberAttributeConfig().setAttribute("__vertx.nodeId", options.getNodeName()); hazelcastInstance = Hazelcast.getOrCreateHazelcastInstance(config); diff --git a/mdm/hibernate-core/src/main/java/com/gentics/mesh/endpoint/admin/HibAdminHandler.java b/mdm/hibernate-core/src/main/java/com/gentics/mesh/endpoint/admin/HibAdminHandler.java index c26117a232..4cf6afbdce 100644 --- a/mdm/hibernate-core/src/main/java/com/gentics/mesh/endpoint/admin/HibAdminHandler.java +++ b/mdm/hibernate-core/src/main/java/com/gentics/mesh/endpoint/admin/HibAdminHandler.java @@ -4,8 +4,24 @@ import static com.gentics.mesh.core.rest.error.Errors.error; import static com.gentics.mesh.rest.Messages.message; import static io.netty.handler.codec.http.HttpResponseStatus.FORBIDDEN; +import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR; import static io.netty.handler.codec.http.HttpResponseStatus.OK; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.tuple.Pair; + +import com.gentics.mesh.MeshVersion; import com.gentics.mesh.cache.CacheRegistry; import com.gentics.mesh.cli.BootstrapInitializer; import com.gentics.mesh.contentoperation.ContentCachedStorage; @@ -17,10 +33,16 @@ import com.gentics.mesh.core.verticle.handler.HandlerUtilities; import com.gentics.mesh.core.verticle.handler.WriteLock; import com.gentics.mesh.distributed.coordinator.Coordinator; +import com.gentics.mesh.etc.config.HttpServerConfig; import com.gentics.mesh.etc.config.MeshOptions; +import com.gentics.mesh.etc.config.Version; +import com.gentics.mesh.http.HttpConstants; import com.gentics.mesh.router.RouterStorageImpl; import com.gentics.mesh.router.RouterStorageRegistryImpl; import com.gentics.mesh.search.SearchProvider; +import com.gentics.mesh.util.MeshOpenAPIv3Generator; +import com.gentics.vertx.openapi.model.Format; +import com.gentics.vertx.openapi.model.OpenAPIGenerationException; import io.vertx.core.Vertx; @@ -57,4 +79,56 @@ public void handleCacheClear(InternalActionContext ac) { return message(ac, "cache_clear_invoked"); }, model -> ac.send(model, OK)); } + + @Override + public void handleOpenAPIv3(InternalActionContext ac, com.gentics.mesh.etc.config.Format formatConf, Version version) { + boolean useVersion31 = version == Version.V31; + String format = formatConf.name().toLowerCase(); + + // Collect available servers + HttpServerConfig httpServerConfig = options.getHttpServerOptions(); + List servers = Collections.singletonList((httpServerConfig.isSsl() ? "https://" : "http://") + httpServerConfig.getHost() + ":" + (httpServerConfig.isSsl() ? httpServerConfig.getSslPort() : httpServerConfig.getPort())); + + /* + * Blacklist + * a) all the actual project roots + * b) old api version roots + * c) an `apiversion` selector parameter root + * d) plugin paths + */ + Set blacklistedRouteRegex = new HashSet<>(routerStorageRegistry.getInstances().stream() + .flatMap(rr -> rr.root().apiRouter().projectsRouter().getProjectRouters().keySet().stream()) + .map(project -> "\\/api\\/v" + MeshVersion.CURRENT_API_VERSION + "\\/" + project + "[.]*").collect(Collectors.toSet())); + blacklistedRouteRegex.addAll(IntStream.range(1, MeshVersion.CURRENT_API_VERSION).mapToObj(v -> "\\/api\\/v" + v + "[.]*").collect(Collectors.toList())); + blacklistedRouteRegex.addAll(List.of("\\/api\\/\\{apiversion\\}[.]*", "\\/api\\/v" + MeshVersion.CURRENT_API_VERSION + "\\/eventbus\\/")); + blacklistedRouteRegex.addAll(List.of("\\/api\\/v" + MeshVersion.CURRENT_API_VERSION + "\\/\\{project\\}\\/plugins[.]*", "\\/api\\/v" + MeshVersion.CURRENT_API_VERSION + "\\/plugins[.]*")); + + // Make an instance with blacklist path patterns + MeshOpenAPIv3Generator generator = new MeshOpenAPIv3Generator(MeshVersion.getPlainVersion(), servers, Optional.of(blacklistedRouteRegex.stream().map(Pattern::compile).collect(Collectors.toList())), Optional.empty()); + + // Generate... + try { + ac.send(generator.generate( + "Gentics Mesh REST API", + Stream.of( + //... from base root + routerStorageRegistry.getInstances().stream().map(rr -> Pair.of(rr.root().getRouter(), StringUtils.EMPTY)), + //... from generic project root + routerStorageRegistry.getInstances().stream().map(rr -> Pair.of(rr.root().apiRouter().projectsRouter().projectRouter().getRouter(), "/api/v" + MeshVersion.CURRENT_API_VERSION + "/{project}")) + ).flatMap(Function.identity()).collect(Collectors.toMap(Pair::getKey, Pair::getValue)), + // ...with desired format + Format.parse(format), + // ...with desired pretty printing + !options.getHttpServerOptions().isMinifyJson(), + // ...with desired spec version + useVersion31), + OK, + "yaml".equalsIgnoreCase(format) + ? HttpConstants.APPLICATION_YAML_UTF8 + : HttpConstants.APPLICATION_JSON_UTF8 + ); + } catch (OpenAPIGenerationException e) { + ac.fail(error(INTERNAL_SERVER_ERROR, "error_internal", e)); + } + } } diff --git a/plugin-api/src/main/java/com/gentics/mesh/plugin/RestPlugin.java b/plugin-api/src/main/java/com/gentics/mesh/plugin/RestPlugin.java index 095fc4f70f..a28e91f05a 100644 --- a/plugin-api/src/main/java/com/gentics/mesh/plugin/RestPlugin.java +++ b/plugin-api/src/main/java/com/gentics/mesh/plugin/RestPlugin.java @@ -8,6 +8,8 @@ import java.util.Optional; import java.util.concurrent.Callable; +import org.apache.commons.lang3.tuple.Pair; + import com.gentics.mesh.etc.config.MeshOptions; import com.gentics.mesh.etc.config.VertxOptions; @@ -45,6 +47,15 @@ default Router createProjectRouter() { return null; } + /** + * Create a pair of routers, global and project. Note that this method will be invoked multiple times in order to register the endpoints to all REST verticles. + * + * @return + */ + default Pair createRouters() { + return Pair.of(createGlobalRouter(), createProjectRouter()); + } + /** * Return a wrapped routing context. * diff --git a/plugin-parent/pom.xml b/plugin-parent/pom.xml index 90129d2d06..48d51e0b52 100644 --- a/plugin-parent/pom.xml +++ b/plugin-parent/pom.xml @@ -42,6 +42,37 @@ mesh-plugin-api provided + + com.gentics + vertx-openapi + provided + + + org.slf4j + slf4j-parent + + + org.slf4j + slf4j-log4j12 + + + org.slf4j + slf4j-api + + + commons-validator + commons-validator + + + com.github.fge + json-schema-validator + + + com.fasterxml.jackson.module + jackson-module-jsonSchema + + + diff --git a/rest-client/src/main/java/com/gentics/mesh/parameter/client/AbstractParameters.java b/rest-client/src/main/java/com/gentics/mesh/parameter/client/AbstractParameters.java index 4832753e2e..e9600b36c3 100644 --- a/rest-client/src/main/java/com/gentics/mesh/parameter/client/AbstractParameters.java +++ b/rest-client/src/main/java/com/gentics/mesh/parameter/client/AbstractParameters.java @@ -5,11 +5,10 @@ import org.raml.model.parameter.QueryParameter; -import com.gentics.mesh.parameter.PagingParameters; import com.gentics.mesh.parameter.ParameterProvider; /** - * Common default implementation for {@link PagingParameters} + * Common default implementation for {@link ParameterProvider} */ public abstract class AbstractParameters implements ParameterProvider { diff --git a/rest-client/src/main/java/com/gentics/mesh/parameter/client/EtagParametersImpl.java b/rest-client/src/main/java/com/gentics/mesh/parameter/client/EtagParametersImpl.java new file mode 100644 index 0000000000..73d6d6f456 --- /dev/null +++ b/rest-client/src/main/java/com/gentics/mesh/parameter/client/EtagParametersImpl.java @@ -0,0 +1,10 @@ +package com.gentics.mesh.parameter.client; + +import com.gentics.mesh.parameter.EtagParameters; + +/** + * @see EtagParameters + */ +public class EtagParametersImpl extends AbstractParameters implements EtagParameters { + +} diff --git a/rest-client/src/main/java/com/gentics/mesh/parameter/client/GenericParametersImpl.java b/rest-client/src/main/java/com/gentics/mesh/parameter/client/GenericParametersImpl.java index 86226f30a2..43a290e512 100644 --- a/rest-client/src/main/java/com/gentics/mesh/parameter/client/GenericParametersImpl.java +++ b/rest-client/src/main/java/com/gentics/mesh/parameter/client/GenericParametersImpl.java @@ -5,6 +5,6 @@ /** * @see GenericParameters */ -public class GenericParametersImpl extends AbstractParameters implements GenericParameters { +public class GenericParametersImpl extends EtagParametersImpl implements GenericParameters { } diff --git a/rest-client/src/main/java/com/gentics/mesh/parameter/client/LanguageParametersImpl.java b/rest-client/src/main/java/com/gentics/mesh/parameter/client/LanguageParametersImpl.java new file mode 100644 index 0000000000..787c0175f8 --- /dev/null +++ b/rest-client/src/main/java/com/gentics/mesh/parameter/client/LanguageParametersImpl.java @@ -0,0 +1,7 @@ +package com.gentics.mesh.parameter.client; + +import com.gentics.mesh.parameter.LanguageParameters; + +public class LanguageParametersImpl extends AbstractParameters implements LanguageParameters { + +} diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/MeshRestClientMessageException.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/MeshRestClientMessageException.java index d49a6e292c..63b5503589 100644 --- a/rest-client/src/main/java/com/gentics/mesh/rest/client/MeshRestClientMessageException.java +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/MeshRestClientMessageException.java @@ -33,7 +33,7 @@ public MeshRestClientMessageException(int statusCode, String statusMessage, Stri } public MeshRestClientMessageException(int statusCode, String statusMessage, GenericMessageResponse responseMessage, HttpMethod method, String uri) { - super("Error:" + statusCode + " in " + method.name() + " " + uri + " : " + statusMessage); + super("Error:" + statusCode + (method != null ? (" in " + method.name()) : "") + " " + uri + " : " + statusMessage); this.responseMessage = responseMessage; this.statusCode = statusCode; this.uri = uri; diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/AbstractMeshOkHttpRequest.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/AbstractMeshOkHttpRequest.java new file mode 100644 index 0000000000..2647350b09 --- /dev/null +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/AbstractMeshOkHttpRequest.java @@ -0,0 +1,193 @@ +package com.gentics.mesh.rest.client.impl; + +import java.io.IOException; +import java.net.URI; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Supplier; + +import org.apache.commons.lang.StringUtils; + +import com.gentics.mesh.core.rest.common.GenericMessageResponse; +import com.gentics.mesh.core.rest.error.GenericRestException; +import com.gentics.mesh.json.JsonUtil; +import com.gentics.mesh.rest.client.MeshBinaryResponse; +import com.gentics.mesh.rest.client.MeshRequest; +import com.gentics.mesh.rest.client.MeshResponse; +import com.gentics.mesh.rest.client.MeshRestClientMessageException; +import com.gentics.mesh.rest.client.MeshWebrootFieldResponse; +import com.gentics.mesh.rest.client.MeshWebrootResponse; + +import io.reactivex.Completable; +import io.reactivex.Single; +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; + +/** + * Default OkHTTP based client implementation + * + * @param + */ +public abstract class AbstractMeshOkHttpRequest implements MeshRequest { + + protected final OkHttpClient client; + protected final Class resultClass; + + public AbstractMeshOkHttpRequest(OkHttpClient client, Class resultClass) { + this.client = client; + this.resultClass = resultClass; + } + + @Override + public Single> getResponse() { + return getOkResponse().map(response -> new MeshResponse() { + Supplier body = Util.lazily(() -> mapResponse(response)); + + @Override + public Map> getHeaders() { + return response.headers().toMultimap(); + } + + @Override + public List getHeaders(String name) { + return response.headers(name); + } + + @Override + public int getStatusCode() { + return response.code(); + } + + @Override + public String getBodyAsString() { + try { + return response.body().string(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public R getBody() { + return body.get(); + } + + @Override + public void close() { + Optional.ofNullable(response).map(Response::body).ifPresent(ResponseBody::close); + } + }); + } + + @Override + public Completable toCompletable() { + return getOkResponse() + .doOnSuccess(this::throwOnError) + .doOnSuccess(response -> Optional.ofNullable(response) + .ifPresent(Response::close)) + .ignoreElement(); + } + + @Override + public Single toSingle() { + return getOkResponse().map(this::mapResponse); + } + + public Single getOkResponse() { + return Single.create(sub -> { + Call call = createCall(); + call.enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + // Don't call the onError twice, but notify about multiple exceptions (should not occur often). + if (sub.isDisposed()) { + e.printStackTrace(); + } else { + sub.onError(new IOException(String.format("I/O Error in %s %s : %s (%s)", + HttpMethod.valueOf(call.request().method().toUpperCase()), call.request().url(), e.getClass().getSimpleName(), e.getLocalizedMessage()), e)); + } + } + + @Override + public void onResponse(Call call, Response response) throws IOException { + if (!sub.isDisposed()) { + sub.onSuccess(response); + } else { + response.close(); + } + } + }); + }); + } + + protected abstract Request createRequest(); + + protected Call createCall() { + return client.newCall(createRequest()); + } + + @SuppressWarnings("unchecked") + private R mapResponse(Response response) throws IOException, MeshRestClientMessageException { + throwOnError(response); + + String contentType = response.header("Content-Type"); + if (!response.isSuccessful()) { + return null; + } else if (resultClass.isAssignableFrom(EmptyResponse.class)) { + return (R) EmptyResponse.getInstance(); + } else if (resultClass.isAssignableFrom(MeshBinaryResponse.class)) { + return (R) new OkHttpBinaryResponse(response); + } else if (resultClass.isAssignableFrom(MeshWebrootResponse.class)) { + return (R) new OkHttpWebrootResponse(response); + } else if (resultClass.isAssignableFrom(MeshWebrootFieldResponse.class)) { + return (R) new OkHttpWebrootFieldResponse(response, false); + } else if (contentType != null && contentType.startsWith("application/json") && !resultClass.isAssignableFrom(String.class)) { + return JsonUtil.readValue(response.body().string(), resultClass); + } else if (resultClass.isAssignableFrom(String.class)) { + return (R) response.body().string(); + } else { + throw new RuntimeException("Request can't be handled by this handler since the content type was {" + contentType + "}"); + } + } + + private void throwOnError(Response response) throws IOException, MeshRestClientMessageException { + if (!response.isSuccessful() && response.code() != 304) { + String body = response.body().string(); + MeshRestClientMessageException err; + try { + GenericMessageResponse msg = null; + if (!StringUtils.isEmpty(body)) { + msg = JsonUtil.readValue(body, GenericMessageResponse.class); + } + err = new MeshRestClientMessageException( + response.code(), + response.message(), + msg, + HttpMethod.valueOf(response.request().method().toUpperCase()), + stripOrigin(response.request().url().toString())); + } catch (GenericRestException e) { + err = new MeshRestClientMessageException( + response.code(), + response.message(), + body, + HttpMethod.valueOf(response.request().method().toUpperCase()), + stripOrigin(response.request().url().toString())); + } + response.close(); + throw err; + } + } + + private String stripOrigin(String url) { + URI uri = URI.create(url); + String query = uri.getQuery(); + return uri.getPath() + (query == null || query.length() == 0 + ? "" + : "?" + query); + } +} diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/MeshOkHttpRequestImpl.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/MeshOkHttpRequestImpl.java index e63e1b6e87..a9ad5163bd 100644 --- a/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/MeshOkHttpRequestImpl.java +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/MeshOkHttpRequestImpl.java @@ -27,7 +27,6 @@ import com.gentics.mesh.rest.client.MeshWebrootFieldResponse; import com.gentics.mesh.rest.client.MeshWebrootResponse; -import io.reactivex.Completable; import io.reactivex.Flowable; import io.reactivex.Observable; import io.reactivex.Single; @@ -53,12 +52,10 @@ * @see MeshRequest * @param */ -public class MeshOkHttpRequestImpl implements MeshRequest { +public class MeshOkHttpRequestImpl extends AbstractMeshOkHttpRequest { private final MeshRestClient meshClient; - private final OkHttpClient client; private final MeshRestClientConfig config; - private final Class resultClass; private final String method; private final String url; @@ -67,10 +64,9 @@ public class MeshOkHttpRequestImpl implements MeshRequest { private MeshOkHttpRequestImpl(MeshRestClient meshClient, OkHttpClient client, MeshRestClientConfig config, Class resultClass, String method, String url, Map headers, RequestBody requestBody) { + super(client, resultClass); this.meshClient = meshClient; - this.client = client; this.config = config; - this.resultClass = resultClass; this.method = method; this.url = url; this.headers = headers; @@ -200,7 +196,8 @@ public void setHeaders(Map headers) { this.headers.putAll(headers); } - private Request createRequest() { + @Override + protected Request createRequest() { Request.Builder builder = new Request.Builder() .url(url) .headers(Headers.of(headers)); @@ -265,20 +262,6 @@ public void onResponse(Call call, Response response) throws IOException { return response.retryWhen(retryOnNetworkErrors(retries, delay)); } - @Override - public Single toSingle() { - return getOkResponse().map(this::mapResponse); - } - - @Override - public Completable toCompletable() { - return getOkResponse() - .doOnSuccess(this::throwOnError) - .doOnSuccess(response -> Optional.ofNullable(response) - .ifPresent(Response::close)) - .ignoreElement(); - } - @SuppressWarnings("unchecked") private T mapResponse(Response response) throws IOException, MeshRestClientMessageException { throwOnError(response); @@ -309,7 +292,7 @@ private T mapResponse(Response response) throws IOException, MeshRestClientMessa return (T) new OkHttpWebrootResponse(response); } else if (resultClass.isAssignableFrom(MeshWebrootFieldResponse.class)) { return (T) new OkHttpWebrootFieldResponse(response, config.isMinifyJson()); - } else if (contentType != null && contentType.startsWith("application/json")) { + } else if (contentType != null && contentType.startsWith("application/json") && !resultClass.isAssignableFrom(String.class)) { return JsonUtil.readValue(response.body().string(), resultClass); } else if (resultClass.isAssignableFrom(String.class)) { return (T) response.body().string(); diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/MeshRestHttpClientImpl.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/MeshRestHttpClientImpl.java index e71cdf1c27..479f7ef8bb 100644 --- a/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/MeshRestHttpClientImpl.java +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/MeshRestHttpClientImpl.java @@ -105,7 +105,6 @@ import com.gentics.mesh.core.rest.user.UserResponse; import com.gentics.mesh.core.rest.user.UserUpdateRequest; import com.gentics.mesh.core.rest.validation.SchemaValidationResponse; -import com.gentics.mesh.parameter.BackupParameters; import com.gentics.mesh.parameter.ImageManipulationParameters; import com.gentics.mesh.parameter.PagingParameters; import com.gentics.mesh.parameter.ParameterProvider; @@ -281,12 +280,12 @@ public MeshRequest findTagByUuid(String projectName, String tagFami } @Override - public MeshRequest updateTag(String projectName, String tagFamilyUuid, String uuid, TagUpdateRequest tagUpdateRequest) { + public MeshRequest updateTag(String projectName, String tagFamilyUuid, String uuid, TagUpdateRequest tagUpdateRequest, ParameterProvider... parameters) { Objects.requireNonNull(projectName, "projectName must not be null"); Objects.requireNonNull(tagUpdateRequest, "tagUpdateRequest must not be null"); Util.requireUuid(tagFamilyUuid, "tagFamilyUuid"); Util.requireUuid(uuid, "uuid"); - return prepareRequest(POST, "/" + encodeSegment(projectName) + "/tagFamilies/" + tagFamilyUuid + "/tags/" + uuid, TagResponse.class, + return prepareRequest(POST, "/" + encodeSegment(projectName) + "/tagFamilies/" + tagFamilyUuid + "/tags/" + uuid + getQuery(getConfig(), parameters), TagResponse.class, tagUpdateRequest); } @@ -420,13 +419,13 @@ public MeshRequest findProjects(ParameterProvider... parame } @Override - public MeshRequest assignLanguageToProject(String projectUuid, String languageUuid) { - return assignLanguageToProjectByUuid(projectUuid, languageUuid); + public MeshRequest assignLanguageToProject(String projectUuid, String languageUuid, ParameterProvider... parameters) { + return assignLanguageToProjectByUuid(projectUuid, languageUuid, parameters); } @Override - public MeshRequest unassignLanguageFromProject(String projectUuid, String languageUuid) { - return unassignLanguageFromProjectByUuid(projectUuid, languageUuid); + public MeshRequest unassignLanguageFromProject(String projectUuid, String languageUuid, ParameterProvider... parameters) { + return unassignLanguageFromProjectByUuid(projectUuid, languageUuid, parameters); } @Override @@ -443,10 +442,10 @@ public MeshRequest createProject(String uuid, ProjectCreateRequ } @Override - public MeshRequest updateProject(String uuid, ProjectUpdateRequest projectUpdateRequest) { + public MeshRequest updateProject(String uuid, ProjectUpdateRequest projectUpdateRequest, ParameterProvider... parameters) { Util.requireUuid(uuid, "uuid"); Objects.requireNonNull(projectUpdateRequest, "projectUpdateRequest must not be null"); - return prepareRequest(POST, "/projects/" + uuid, ProjectResponse.class, projectUpdateRequest); + return prepareRequest(POST, "/projects/" + uuid + getQuery(getConfig(), parameters), ProjectResponse.class, projectUpdateRequest); } @Override @@ -529,11 +528,11 @@ public MeshRequest deleteTagFamily(String projectName, String uui } @Override - public MeshRequest updateTagFamily(String projectName, String tagFamilyUuid, TagFamilyUpdateRequest tagFamilyUpdateRequest) { + public MeshRequest updateTagFamily(String projectName, String tagFamilyUuid, TagFamilyUpdateRequest tagFamilyUpdateRequest, ParameterProvider... parameters) { Objects.requireNonNull(projectName, "projectName must not be null"); Util.requireUuid(tagFamilyUuid, "tagFamilyUuid"); Objects.requireNonNull(tagFamilyUpdateRequest, "tagFamilyUpdateRequest must not be null"); - return prepareRequest(POST, "/" + encodeSegment(projectName) + "/tagFamilies/" + tagFamilyUuid, TagFamilyResponse.class, + return prepareRequest(POST, "/" + encodeSegment(projectName) + "/tagFamilies/" + tagFamilyUuid + getQuery(getConfig(), parameters), TagFamilyResponse.class, tagFamilyUpdateRequest); } @@ -571,10 +570,10 @@ public MeshRequest createGroup(String uuid, GroupCreateRequest gr } @Override - public MeshRequest updateGroup(String uuid, GroupUpdateRequest groupUpdateRequest) { + public MeshRequest updateGroup(String uuid, GroupUpdateRequest groupUpdateRequest, ParameterProvider... parameters) { Util.requireUuid(uuid, "uuid"); Objects.requireNonNull(groupUpdateRequest, "groupUpdateRequest must not be null"); - return prepareRequest(POST, "/groups/" + uuid, GroupResponse.class, groupUpdateRequest); + return prepareRequest(POST, "/groups/" + uuid + getQuery(getConfig(), parameters), GroupResponse.class, groupUpdateRequest); } @Override @@ -807,10 +806,10 @@ public MeshRequest createSchema(String uuid, SchemaCreateRequest } @Override - public MeshRequest updateRole(String uuid, RoleUpdateRequest restRole) { + public MeshRequest updateRole(String uuid, RoleUpdateRequest restRole, ParameterProvider... parameters) { Util.requireUuid(uuid, "uuid"); Objects.requireNonNull(restRole, "restRole must not be null"); - return prepareRequest(POST, "/roles/" + uuid, RoleResponse.class, restRole); + return prepareRequest(POST, "/roles/" + uuid + getQuery(getConfig(), parameters), RoleResponse.class, restRole); } @Override @@ -984,9 +983,9 @@ public MeshRequest searchUsers(String json, ParameterProvider. } @Override - public MeshRequest searchUsersRaw(String json) { + public MeshRequest searchUsersRaw(String json, ParameterProvider... parameters) { Objects.requireNonNull(json, "json must not be null"); - return handleRequest(POST, "/rawSearch/users", ObjectNode.class, json); + return handleRequest(POST, "/rawSearch/users" + getQuery(getConfig(), parameters), ObjectNode.class, json); } @Override @@ -996,9 +995,9 @@ public MeshRequest searchGroups(String json, ParameterProvide } @Override - public MeshRequest searchGroupsRaw(String json) { + public MeshRequest searchGroupsRaw(String json, ParameterProvider... parameters) { Objects.requireNonNull(json, "json must not be null"); - return handleRequest(POST, "/rawSearch/groups", ObjectNode.class, json); + return handleRequest(POST, "/rawSearch/groups" + getQuery(getConfig(), parameters), ObjectNode.class, json); } @Override @@ -1008,9 +1007,9 @@ public MeshRequest searchRoles(String json, ParameterProvider. } @Override - public MeshRequest searchRolesRaw(String json) { + public MeshRequest searchRolesRaw(String json, ParameterProvider... parameters) { Objects.requireNonNull(json, "json must not be null"); - return handleRequest(POST, "/rawSearch/roles", ObjectNode.class, json); + return handleRequest(POST, "/rawSearch/roles" + getQuery(getConfig(), parameters), ObjectNode.class, json); } @Override @@ -1020,9 +1019,9 @@ public MeshRequest searchMicroschemas(String json, Para } @Override - public MeshRequest searchMicroschemasRaw(String json) { + public MeshRequest searchMicroschemasRaw(String json, ParameterProvider... parameters) { Objects.requireNonNull(json, "json must not be null"); - return handleRequest(POST, "/rawSearch/microschemas", ObjectNode.class, json); + return handleRequest(POST, "/rawSearch/microschemas" + getQuery(getConfig(), parameters), ObjectNode.class, json); } @Override @@ -1032,9 +1031,9 @@ public MeshRequest searchProjects(String json, ParameterPro } @Override - public MeshRequest searchProjectsRaw(String json) { + public MeshRequest searchProjectsRaw(String json, ParameterProvider... parameters) { Objects.requireNonNull(json, "json must not be null"); - return handleRequest(POST, "/rawSearch/projects", ObjectNode.class, json); + return handleRequest(POST, "/rawSearch/projects" + getQuery(getConfig(), parameters), ObjectNode.class, json); } @Override @@ -1044,9 +1043,9 @@ public MeshRequest searchTags(String json, ParameterProvider... } @Override - public MeshRequest searchTagsRaw(String json) { + public MeshRequest searchTagsRaw(String json, ParameterProvider... parameters) { Objects.requireNonNull(json, "json must not be null"); - return handleRequest(POST, "/rawSearch/tags", ObjectNode.class, json); + return handleRequest(POST, "/rawSearch/tags" + getQuery(getConfig(), parameters), ObjectNode.class, json); } @Override @@ -1057,10 +1056,10 @@ public MeshRequest searchTags(String projectName, String json, } @Override - public MeshRequest searchTagsRaw(String projectName, String json) { + public MeshRequest searchTagsRaw(String projectName, String json, ParameterProvider... parameters) { Objects.requireNonNull(projectName, "projectName must not be null"); Objects.requireNonNull(json, "json must not be null"); - return handleRequest(POST, "/" + encodeSegment(projectName) + "/rawSearch/tags", ObjectNode.class, json); + return handleRequest(POST, "/" + encodeSegment(projectName) + "/rawSearch/tags" + getQuery(getConfig(), parameters), ObjectNode.class, json); } @Override @@ -1070,9 +1069,9 @@ public MeshRequest searchSchemas(String json, ParameterProvi } @Override - public MeshRequest searchSchemasRaw(String json) { + public MeshRequest searchSchemasRaw(String json, ParameterProvider... parameters) { Objects.requireNonNull(json, "json must not be null"); - return handleRequest(POST, "/rawSearch/schemas", ObjectNode.class, json); + return handleRequest(POST, "/rawSearch/schemas" + getQuery(getConfig(), parameters), ObjectNode.class, json); } @Override @@ -1082,9 +1081,9 @@ public MeshRequest searchTagFamilies(String json, Paramet } @Override - public MeshRequest searchTagFamiliesRaw(String json) { + public MeshRequest searchTagFamiliesRaw(String json, ParameterProvider... parameters) { Objects.requireNonNull(json, "json must not be null"); - return handleRequest(POST, "/rawSearch/tagFamilies", ObjectNode.class, json); + return handleRequest(POST, "/rawSearch/tagFamilies" + getQuery(getConfig(), parameters), ObjectNode.class, json); } @Override @@ -1096,10 +1095,10 @@ public MeshRequest searchTagFamilies(String projectName, } @Override - public MeshRequest searchTagFamiliesRaw(String projectName, String json) { + public MeshRequest searchTagFamiliesRaw(String projectName, String json, ParameterProvider... parameters) { Objects.requireNonNull(projectName, "projectName must not be null"); Objects.requireNonNull(json, "json must not be null"); - return handleRequest(POST, "/" + encodeSegment(projectName) + "/rawSearch/tagFamilies", ObjectNode.class, json); + return handleRequest(POST, "/" + encodeSegment(projectName) + "/rawSearch/tagFamilies" + getQuery(getConfig(), parameters), ObjectNode.class, json); } @Override @@ -1117,31 +1116,6 @@ public MeshRequest searchStatus() { return prepareRequest(GET, "/search/status", SearchStatusResponse.class); } - @Override - public MeshRequest invokeBackup() { - return prepareRequest(POST, "/admin/graphdb/backup", GenericMessageResponse.class); - } - - @Override - public MeshRequest invokeBackup(BackupParameters parameters) { - return prepareRequest(POST, "/admin/graphdb/backup" + getQuery(getConfig(), parameters), GenericMessageResponse.class); - } - - @Override - public MeshRequest invokeExport() { - return prepareRequest(POST, "/admin/graphdb/export", GenericMessageResponse.class); - } - - @Override - public MeshRequest invokeImport() { - return prepareRequest(POST, "/admin/graphdb/import", GenericMessageResponse.class); - } - - @Override - public MeshRequest invokeRestore() { - return prepareRequest(POST, "/admin/graphdb/restore", GenericMessageResponse.class); - } - @Override public MeshRequest checkConsistency(ParameterProvider... parameters) { return prepareRequest(GET, "/admin/consistency/check" + getQuery(getConfig(), parameters), ConsistencyCheckResponse.class); @@ -1223,18 +1197,13 @@ public MeshRequest downloadBinaryField(String projectName, S @Override public MeshRequest downloadBinaryField(String projectName, String nodeUuid, String languageTag, String fieldKey, long from, long to, ParameterProvider... parameters) { - Objects.requireNonNull(projectName, "projectName must not be null"); - Util.requireUuid(nodeUuid, "nodeUuid"); - Objects.requireNonNull(fieldKey, "fieldKey must not be null"); Util.requireNonNegative(from, "from"); Util.requireNonNegative(to, "to"); if (to < from) { throw new InvalidParameterException(String.format("Parameter to must be equal or greater then from. Given values: %d-%d", from, to)); } - String path = "/" + encodeSegment(projectName) + "/nodes/" + nodeUuid + "/binary/" + encodeSegment(fieldKey) + getQuery(getConfig(), parameters); - - MeshRequest request = prepareRequest(GET, path, MeshBinaryResponse.class); + MeshRequest request = downloadBinaryField(projectName, nodeUuid, languageTag, fieldKey, parameters); request.setHeader("Range", String.format("bytes=%d-%d", from, to)); return request; } @@ -1402,11 +1371,11 @@ public MeshRequest findBranches(String projectName, Paramete } @Override - public MeshRequest updateBranch(String projectName, String branchUuid, BranchUpdateRequest request) { + public MeshRequest updateBranch(String projectName, String branchUuid, BranchUpdateRequest request, ParameterProvider... parameters) { Objects.requireNonNull(projectName, "projectName must not be null"); Util.requireUuid(branchUuid, "branchUuid"); - return prepareRequest(POST, "/" + encodeSegment(projectName) + "/branches/" + branchUuid, BranchResponse.class, request); + return prepareRequest(POST, "/" + encodeSegment(projectName) + "/branches/" + branchUuid + getQuery(getConfig(), parameters), BranchResponse.class, request); } @Override @@ -1422,11 +1391,18 @@ public MeshRequest getRAML() { } @Override - public MeshRequest getBranchSchemaVersions(String projectName, String branchUuid) { + public MeshRequest getOpenAPI() { + MeshRequest request = prepareRequest(GET, "/openapi.yaml" + getQuery(getConfig()), String.class); + request.setHeader("Accept", "*/*"); + return request; + } + + @Override + public MeshRequest getBranchSchemaVersions(String projectName, String branchUuid, ParameterProvider... parameters) { Objects.requireNonNull(projectName, "projectName must not be null"); Util.requireUuid(branchUuid, "branchUuid"); - return prepareRequest(GET, "/" + encodeSegment(projectName) + "/branches/" + branchUuid + "/schemas", BranchInfoSchemaList.class); + return prepareRequest(GET, "/" + encodeSegment(projectName) + "/branches/" + branchUuid + "/schemas" + getQuery(getConfig(), parameters), BranchInfoSchemaList.class); } @Override @@ -1449,11 +1425,11 @@ public MeshRequest assignBranchSchemaVersions(String proje } @Override - public MeshRequest getBranchMicroschemaVersions(String projectName, String branchUuid) { + public MeshRequest getBranchMicroschemaVersions(String projectName, String branchUuid, ParameterProvider... parameters) { Objects.requireNonNull(projectName, "projectName must not be null"); Util.requireUuid(branchUuid, "branchUuid"); - return prepareRequest(GET, "/" + encodeSegment(projectName) + "/branches/" + branchUuid + "/microschemas", + return prepareRequest(GET, "/" + encodeSegment(projectName) + "/branches/" + branchUuid + "/microschemas" + getQuery(getConfig(), parameters), BranchInfoMicroschemaList.class); } @@ -1921,9 +1897,9 @@ public MeshRequest revokeProjectRolePermissions(String } @Override - public MeshRequest getRoleRolePermissions(String uuid) { + public MeshRequest getRoleRolePermissions(String uuid, ParameterProvider... parameters) { Util.requireUuid(uuid, "uuid"); - return prepareRequest(GET, "/roles/" + uuid + "/rolePermissions", ObjectPermissionResponse.class); + return prepareRequest(GET, "/roles/" + uuid + "/rolePermissions" + getQuery(getConfig(), parameters), ObjectPermissionResponse.class); } @Override diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/OkHttpWebsocket.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/OkHttpWebsocket.java index 00378f696b..5d3226cc8e 100644 --- a/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/OkHttpWebsocket.java +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/OkHttpWebsocket.java @@ -1,19 +1,33 @@ package com.gentics.mesh.rest.client.impl; +import static com.gentics.mesh.rest.client.impl.Util.eventbusMessage; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Stream; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.gentics.mesh.json.JsonUtil; import com.gentics.mesh.rest.client.EventbusEvent; import com.gentics.mesh.rest.client.MeshRestClientConfig; import com.gentics.mesh.rest.client.MeshWebsocket; + import io.reactivex.Completable; import io.reactivex.Maybe; import io.reactivex.Observable; import io.reactivex.disposables.Disposable; import io.reactivex.subjects.PublishSubject; import io.reactivex.subjects.Subject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; @@ -21,19 +35,6 @@ import okhttp3.WebSocketListener; import okio.ByteString; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Stream; - -import static com.gentics.mesh.rest.client.impl.Util.eventbusMessage; - /** * Websocket client implementation for {@link OkHttpClient}. */ diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/Util.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/Util.java index 9bf123f7e6..4787ef5775 100644 --- a/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/Util.java +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/impl/Util.java @@ -3,6 +3,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.security.InvalidParameterException; +import java.util.concurrent.Callable; import java.util.function.Supplier; import java.util.stream.Stream; @@ -79,7 +80,7 @@ public static String eventbusMessage(EventbusMessageType type, String address, O * @param * @return */ - public static Supplier lazily(WrappedSupplier supplier) { + public static Supplier lazily(Callable supplier) { return new Supplier() { T value; boolean supplied = false; @@ -88,7 +89,7 @@ public static Supplier lazily(WrappedSupplier supplier) { public synchronized T get() { if (!supplied) { try { - value = supplier.get(); + value = supplier.call(); supplied = true; } catch (Exception e) { throw new RuntimeException(e); @@ -170,8 +171,4 @@ public static String normalizedPath(String path) throws URISyntaxException { return Strings.CI.removeStart(normalizedURI, "http://host"); } - - interface WrappedSupplier { - T get() throws Exception; - } } diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/AdminClientMethods.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/AdminClientMethods.java index 18fd0956f8..e219515282 100644 --- a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/AdminClientMethods.java +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/AdminClientMethods.java @@ -34,44 +34,6 @@ public interface AdminClientMethods { @Deprecated MeshRequest clusterStatus(); - /** - * Invoke a graph database backup. - * - * @return - */ - MeshRequest invokeBackup(); - - /** - * Invoke a graph database backup. - * @return - */ - MeshRequest invokeBackup(BackupParameters parameters); - - /** - * Invoke a graph database export. - * - * @return - * @deprecated Endpoint currently not supported - */ - @Deprecated - MeshRequest invokeExport(); - - /** - * Invoke a graph database restore. - * - * @return - */ - MeshRequest invokeRestore(); - - /** - * Invoke a graph database import. - * - * @return - * @deprecated Endpoint currently not supported - */ - @Deprecated - MeshRequest invokeImport(); - /** * Invoke a consistency check of the graph database. * diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/ApiInfoClientMethods.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/ApiInfoClientMethods.java index 374e94cc4b..1b8dd4d790 100644 --- a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/ApiInfoClientMethods.java +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/ApiInfoClientMethods.java @@ -24,4 +24,11 @@ public interface ApiInfoClientMethods { * @return */ MeshRequest getRAML(); + + /** + * Generate an OpenAPI specification + * + * @return + */ + MeshRequest getOpenAPI(); } diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/BranchClientMethods.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/BranchClientMethods.java index 46906da38a..7fc34484ec 100644 --- a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/BranchClientMethods.java +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/BranchClientMethods.java @@ -72,7 +72,7 @@ MeshRequest createBranch(String projectName, String uuid, Branch * @param request * @return */ - MeshRequest updateBranch(String projectName, String branchUuid, BranchUpdateRequest request); + MeshRequest updateBranch(String projectName, String branchUuid, BranchUpdateRequest request, ParameterProvider... parameters); /** * Get schema versions assigned to a branch. @@ -81,7 +81,7 @@ MeshRequest createBranch(String projectName, String uuid, Branch * @param branchUuid * @return */ - MeshRequest getBranchSchemaVersions(String projectName, String branchUuid); + MeshRequest getBranchSchemaVersions(String projectName, String branchUuid, ParameterProvider... parameters); /** * Assign the given schema versions to the branch. @@ -110,7 +110,7 @@ MeshRequest createBranch(String projectName, String uuid, Branch * @param branchUuid * @return */ - MeshRequest getBranchMicroschemaVersions(String projectName, String branchUuid); + MeshRequest getBranchMicroschemaVersions(String projectName, String branchUuid, ParameterProvider... parameters); /** * Assign the given microschema versions to the branch. diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/GroupClientMethods.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/GroupClientMethods.java index fdae5c62e7..090f0b6452 100644 --- a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/GroupClientMethods.java +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/GroupClientMethods.java @@ -57,7 +57,7 @@ public interface GroupClientMethods { * @param request * @return */ - MeshRequest updateGroup(String uuid, GroupUpdateRequest request); + MeshRequest updateGroup(String uuid, GroupUpdateRequest request, ParameterProvider... parameters); /** * Delete the group. diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/ProjectClientMethods.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/ProjectClientMethods.java index 9277f4f9a2..96c307e2ec 100644 --- a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/ProjectClientMethods.java +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/ProjectClientMethods.java @@ -51,7 +51,7 @@ public interface ProjectClientMethods { * @param languageUuid * @return */ - MeshRequest assignLanguageToProject(String projectUuid, String languageUuid); + MeshRequest assignLanguageToProject(String projectUuid, String languageUuid, ParameterProvider... parameters); /** * Unassign the given language from the project. @@ -60,7 +60,7 @@ public interface ProjectClientMethods { * @param languageUuid * @return */ - MeshRequest unassignLanguageFromProject(String projectUuid, String languageUuid); + MeshRequest unassignLanguageFromProject(String projectUuid, String languageUuid, ParameterProvider... parameters); /** * Create a new project. @@ -88,7 +88,7 @@ public interface ProjectClientMethods { * @param request * @return */ - MeshRequest updateProject(String uuid, ProjectUpdateRequest request); + MeshRequest updateProject(String uuid, ProjectUpdateRequest request, ParameterProvider... parameters); /** * Delete the project. diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/RoleClientMethods.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/RoleClientMethods.java index b65478a8ad..938cf0d3ad 100644 --- a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/RoleClientMethods.java +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/RoleClientMethods.java @@ -101,7 +101,7 @@ public interface RoleClientMethods { * @param restRole * @return */ - MeshRequest updateRole(String uuid, RoleUpdateRequest restRole); + MeshRequest updateRole(String uuid, RoleUpdateRequest restRole, ParameterProvider... parameters); /** * Get the role permissions on the role @@ -110,7 +110,7 @@ public interface RoleClientMethods { * Uuid of the role * @return request */ - MeshRequest getRoleRolePermissions(String uuid); + MeshRequest getRoleRolePermissions(String uuid, ParameterProvider... parameters); /** * Grant permissions on the role to roles diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/SearchClientMethods.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/SearchClientMethods.java index a227bc9ce3..3b27ce16a5 100644 --- a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/SearchClientMethods.java +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/SearchClientMethods.java @@ -77,7 +77,7 @@ public interface SearchClientMethods { * @param json * @return */ - MeshRequest searchUsersRaw(String json); + MeshRequest searchUsersRaw(String json, ParameterProvider... parameters); /** * Search groups. @@ -95,7 +95,7 @@ public interface SearchClientMethods { * @param json * @return */ - MeshRequest searchGroupsRaw(String json); + MeshRequest searchGroupsRaw(String json, ParameterProvider... parameters); /** * Search roles. @@ -113,7 +113,7 @@ public interface SearchClientMethods { * @param json * @return */ - MeshRequest searchRolesRaw(String json); + MeshRequest searchRolesRaw(String json, ParameterProvider... parameters); /** * Search projects. @@ -131,7 +131,7 @@ public interface SearchClientMethods { * @param json * @return */ - MeshRequest searchProjectsRaw(String json); + MeshRequest searchProjectsRaw(String json, ParameterProvider... parameters); /** * Search tags. @@ -149,7 +149,7 @@ public interface SearchClientMethods { * @param json * @return */ - MeshRequest searchTagsRaw(String json); + MeshRequest searchTagsRaw(String json, ParameterProvider... parameters); /** * Search tags in project @@ -170,7 +170,7 @@ public interface SearchClientMethods { * @param json * @return */ - MeshRequest searchTagsRaw(String projectName, String json); + MeshRequest searchTagsRaw(String projectName, String json, ParameterProvider... parameters); /** * Search tag families. @@ -187,7 +187,7 @@ public interface SearchClientMethods { * @param json * @return */ - MeshRequest searchTagFamiliesRaw(String json); + MeshRequest searchTagFamiliesRaw(String json, ParameterProvider... parameters); /** * Search tag families in project. @@ -206,7 +206,7 @@ public interface SearchClientMethods { * @param json * @return */ - MeshRequest searchTagFamiliesRaw(String projectName, String json); + MeshRequest searchTagFamiliesRaw(String projectName, String json, ParameterProvider... parameters); /** * Search schemas. @@ -224,7 +224,7 @@ public interface SearchClientMethods { * @param json * @return */ - MeshRequest searchSchemasRaw(String json); + MeshRequest searchSchemasRaw(String json, ParameterProvider... parameters); /** * Search microschemas. @@ -243,7 +243,7 @@ public interface SearchClientMethods { * Elasticsearch search request * @return */ - MeshRequest searchMicroschemasRaw(String json); + MeshRequest searchMicroschemasRaw(String json, ParameterProvider... parameters); /** * Clear all search indices by removing and re-creating them. diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/TagClientMethods.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/TagClientMethods.java index f57da8ba48..5174b57336 100644 --- a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/TagClientMethods.java +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/TagClientMethods.java @@ -53,7 +53,7 @@ public interface TagClientMethods { * Update request * @return */ - MeshRequest updateTag(String projectName, String tagFamilyUuid, String uuid, TagUpdateRequest request); + MeshRequest updateTag(String projectName, String tagFamilyUuid, String uuid, TagUpdateRequest request, ParameterProvider... parameters); /** * Create the tag with the given uuid diff --git a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/TagFamilyClientMethods.java b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/TagFamilyClientMethods.java index bf6e9d3bfa..3ca322fd52 100644 --- a/rest-client/src/main/java/com/gentics/mesh/rest/client/method/TagFamilyClientMethods.java +++ b/rest-client/src/main/java/com/gentics/mesh/rest/client/method/TagFamilyClientMethods.java @@ -70,7 +70,7 @@ public interface TagFamilyClientMethods { * Update request * @return */ - MeshRequest updateTagFamily(String projectName, String tagFamilyUuid, TagFamilyUpdateRequest request); + MeshRequest updateTagFamily(String projectName, String tagFamilyUuid, TagFamilyUpdateRequest request, ParameterProvider... parameters); /** * Create the tag family with the given uuid. diff --git a/rest-model/pom.xml b/rest-model/pom.xml index f60789fc2f..d826722cd7 100644 --- a/rest-model/pom.xml +++ b/rest-model/pom.xml @@ -34,31 +34,9 @@ com.gentics.mesh mesh-api - - - com.fasterxml.jackson.core - jackson-annotations - - - com.google.guava - guava - - - com.fasterxml.jackson.module - jackson-module-jsonSchema - - - org.codehaus.jettison - jettison - 1.5.4 - - - commons-io - commons-io - - org.raml - raml-parser + com.gentics + vertx-openapi org.slf4j @@ -86,6 +64,27 @@ + + com.fasterxml.jackson.core + jackson-annotations + + + com.google.guava + guava + + + com.fasterxml.jackson.module + jackson-module-jsonSchema + + + org.codehaus.jettison + jettison + 1.5.4 + + + commons-io + commons-io + diff --git a/rest-model/src/main/java/com/gentics/mesh/core/rest/admin/localconfig/LocalConfigModel.java b/rest-model/src/main/java/com/gentics/mesh/core/rest/admin/localconfig/LocalConfigModel.java index 051a86b3fc..75620e5d83 100644 --- a/rest-model/src/main/java/com/gentics/mesh/core/rest/admin/localconfig/LocalConfigModel.java +++ b/rest-model/src/main/java/com/gentics/mesh/core/rest/admin/localconfig/LocalConfigModel.java @@ -12,6 +12,8 @@ */ public class LocalConfigModel implements RestModel, Serializable { + private static final long serialVersionUID = 7018419343844051338L; + @JsonProperty @JsonPropertyDescription("If true, mutating requests to this instance are not allowed.") private Boolean readOnly = false; diff --git a/rest-model/src/main/java/com/gentics/mesh/core/rest/auth/TokenResponse.java b/rest-model/src/main/java/com/gentics/mesh/core/rest/auth/TokenResponse.java index 64ba7d72d9..3e057f67dc 100644 --- a/rest-model/src/main/java/com/gentics/mesh/core/rest/auth/TokenResponse.java +++ b/rest-model/src/main/java/com/gentics/mesh/core/rest/auth/TokenResponse.java @@ -1,11 +1,16 @@ package com.gentics.mesh.core.rest.auth; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; import com.gentics.mesh.core.rest.common.RestModel; /** * This response is returned when a new JWToken is requested. */ public class TokenResponse implements RestModel { + + @JsonProperty(required = false) + @JsonPropertyDescription("A current JWT access token") private String token; public String getToken() { diff --git a/rest-model/src/main/java/com/gentics/mesh/core/rest/common/GenericMessageResponse.java b/rest-model/src/main/java/com/gentics/mesh/core/rest/common/GenericMessageResponse.java index 9692005e64..04cb493aa6 100644 --- a/rest-model/src/main/java/com/gentics/mesh/core/rest/common/GenericMessageResponse.java +++ b/rest-model/src/main/java/com/gentics/mesh/core/rest/common/GenericMessageResponse.java @@ -4,17 +4,14 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.gentics.vertx.openapi.model.MessageResponse; /** * The {@link GenericMessageResponse} is used when a generic message should be returned to the requester. */ -public class GenericMessageResponse implements RestModel { +public class GenericMessageResponse extends MessageResponse implements RestModel { - @JsonProperty(required = true) - @JsonPropertyDescription("Enduser friendly translated message. Translation depends on the 'Accept-Language' header value") - private String message; - - @JsonProperty(required = true) + @JsonProperty(required = false) @JsonPropertyDescription("Internal developer friendly message") private String internalMessage; @@ -26,6 +23,7 @@ public class GenericMessageResponse implements RestModel { * Create a new generic message response POJO. */ public GenericMessageResponse() { + super(); } /** @@ -47,29 +45,10 @@ public GenericMessageResponse(String message) { * Internal message which may describe the message in a more technical fashion */ public GenericMessageResponse(String message, String internalMessage) { - this.message = message; + super(message); this.internalMessage = internalMessage; } - /** - * Return the message string. - * - * @return Message - */ - public String getMessage() { - return message; - } - - /** - * Set the message string. - * - * @param message - * Message - */ - public void setMessage(String message) { - this.message = message; - } - /** * Return the internal message. * diff --git a/rest-model/src/main/java/com/gentics/mesh/core/rest/common/NameUuidReference.java b/rest-model/src/main/java/com/gentics/mesh/core/rest/common/NameUuidReference.java index d36d462926..9f0a22ef3e 100644 --- a/rest-model/src/main/java/com/gentics/mesh/core/rest/common/NameUuidReference.java +++ b/rest-model/src/main/java/com/gentics/mesh/core/rest/common/NameUuidReference.java @@ -5,7 +5,7 @@ * * @param */ -public interface NameUuidReference { +public interface NameUuidReference extends RestModel { /** * Return the name of the referenced element. diff --git a/rest-model/src/main/java/com/gentics/mesh/core/rest/common/PagingMetaInfo.java b/rest-model/src/main/java/com/gentics/mesh/core/rest/common/PagingMetaInfo.java index cfebe14491..abb891e423 100644 --- a/rest-model/src/main/java/com/gentics/mesh/core/rest/common/PagingMetaInfo.java +++ b/rest-model/src/main/java/com/gentics/mesh/core/rest/common/PagingMetaInfo.java @@ -6,13 +6,13 @@ /** * Paging meta info model. */ -public class PagingMetaInfo { +public class PagingMetaInfo implements RestModel { @JsonProperty(required = true) @JsonPropertyDescription("Number of the current page.") private long currentPage; - @JsonProperty(required = true) + @JsonProperty(required = false) @JsonPropertyDescription("Number of elements which can be included in a single page.") private Long perPage; diff --git a/rest-model/src/main/java/com/gentics/mesh/core/rest/common/RestModel.java b/rest-model/src/main/java/com/gentics/mesh/core/rest/common/RestModel.java index b1a89fa6c9..ee432ede4a 100644 --- a/rest-model/src/main/java/com/gentics/mesh/core/rest/common/RestModel.java +++ b/rest-model/src/main/java/com/gentics/mesh/core/rest/common/RestModel.java @@ -9,22 +9,8 @@ * Marker interface for all rest models. */ @GenerateDocumentation -public interface RestModel extends Shareable { +public interface RestModel extends com.gentics.vertx.openapi.model.RestModel, Shareable { - /** - * Transforms the model into a JSON string, with pretty formatting. - * - * @return - */ - default String toJson() { - return toJson(true); - } - - /** - * Transforms the model into a JSON string. - * - * @return - */ default String toJson(boolean minify) { return JsonUtil.toJson(this, minify); } diff --git a/rest-model/src/main/java/com/gentics/mesh/core/rest/job/JobResponse.java b/rest-model/src/main/java/com/gentics/mesh/core/rest/job/JobResponse.java index 668c05fa92..765fbf9ffa 100644 --- a/rest-model/src/main/java/com/gentics/mesh/core/rest/job/JobResponse.java +++ b/rest-model/src/main/java/com/gentics/mesh/core/rest/job/JobResponse.java @@ -16,7 +16,7 @@ */ public class JobResponse extends AbstractResponse { - @JsonProperty(required = true) + @JsonProperty(required = false) @JsonPropertyDescription("User reference of the creator of the element.") private UserReference creator; @@ -44,11 +44,11 @@ public class JobResponse extends AbstractResponse { @JsonPropertyDescription("Properties of the job.") private Map properties = new HashMap<>(); - @JsonProperty(required = true) + @JsonProperty(required = false) @JsonPropertyDescription("The stop date of the job.") private String stopDate; - @JsonProperty(required = true) + @JsonProperty(required = false) @JsonPropertyDescription("The start date of the job.") private String startDate; diff --git a/rest-model/src/main/java/com/gentics/mesh/core/rest/navigation/NavigationElement.java b/rest-model/src/main/java/com/gentics/mesh/core/rest/navigation/NavigationElement.java index 919821822a..00326b25c5 100644 --- a/rest-model/src/main/java/com/gentics/mesh/core/rest/navigation/NavigationElement.java +++ b/rest-model/src/main/java/com/gentics/mesh/core/rest/navigation/NavigationElement.java @@ -3,12 +3,13 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.gentics.mesh.core.rest.common.RestModel; import com.gentics.mesh.core.rest.node.NodeResponse; /** * A navigation element is a reference to a node within the navigation tree. */ -public class NavigationElement { +public class NavigationElement implements RestModel { @JsonPropertyDescription("Uuid of the node within this navigation element.") private String uuid; diff --git a/rest-model/src/main/java/com/gentics/mesh/core/rest/node/field/NodeFieldListItem.java b/rest-model/src/main/java/com/gentics/mesh/core/rest/node/field/NodeFieldListItem.java index 77b483b70c..379d078e8b 100644 --- a/rest-model/src/main/java/com/gentics/mesh/core/rest/node/field/NodeFieldListItem.java +++ b/rest-model/src/main/java/com/gentics/mesh/core/rest/node/field/NodeFieldListItem.java @@ -1,9 +1,11 @@ package com.gentics.mesh.core.rest.node.field; +import com.gentics.mesh.core.rest.common.RestModel; + /** * Entry for a node list REST model. */ -public interface NodeFieldListItem { +public interface NodeFieldListItem extends RestModel { /** * Return the item node uuid. diff --git a/rest-model/src/main/java/com/gentics/mesh/core/rest/schema/BinaryExtractOptions.java b/rest-model/src/main/java/com/gentics/mesh/core/rest/schema/BinaryExtractOptions.java index c746219e8f..1b8d1dddc8 100644 --- a/rest-model/src/main/java/com/gentics/mesh/core/rest/schema/BinaryExtractOptions.java +++ b/rest-model/src/main/java/com/gentics/mesh/core/rest/schema/BinaryExtractOptions.java @@ -1,9 +1,11 @@ package com.gentics.mesh.core.rest.schema; +import com.gentics.mesh.core.rest.common.RestModel; + /** * Determines what parts of the binary data should be extracted and sent to Elasticsearch. */ -public class BinaryExtractOptions { +public class BinaryExtractOptions implements RestModel { private boolean content; private boolean metadata; diff --git a/rest-model/src/main/java/com/gentics/mesh/core/rest/schema/FieldSchema.java b/rest-model/src/main/java/com/gentics/mesh/core/rest/schema/FieldSchema.java index b9d8465622..4ad1db7474 100644 --- a/rest-model/src/main/java/com/gentics/mesh/core/rest/schema/FieldSchema.java +++ b/rest-model/src/main/java/com/gentics/mesh/core/rest/schema/FieldSchema.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.gentics.mesh.core.rest.common.RestModel; import com.gentics.mesh.core.rest.schema.change.impl.SchemaChangeModel; import com.gentics.mesh.etc.config.search.ElasticSearchOptions; import com.gentics.mesh.etc.config.search.MappingMode; @@ -16,7 +17,7 @@ * A field schema is a field within a schema. In contradiction to node fields a field schema is the blueprint of a field and will not store any data. Instead it * only defines a field within a schema. */ -public interface FieldSchema { +public interface FieldSchema extends RestModel { /** * Return the type of the field schema. diff --git a/rest-model/src/main/java/com/gentics/mesh/core/rest/schema/S3BinaryExtractOptions.java b/rest-model/src/main/java/com/gentics/mesh/core/rest/schema/S3BinaryExtractOptions.java index ef8919272a..5f4b4928b7 100644 --- a/rest-model/src/main/java/com/gentics/mesh/core/rest/schema/S3BinaryExtractOptions.java +++ b/rest-model/src/main/java/com/gentics/mesh/core/rest/schema/S3BinaryExtractOptions.java @@ -1,9 +1,11 @@ package com.gentics.mesh.core.rest.schema; +import com.gentics.mesh.core.rest.common.RestModel; + /** * Determines what parts of the s3binary data should be extracted and sent to Elasticsearch. */ -public class S3BinaryExtractOptions { +public class S3BinaryExtractOptions implements RestModel { private boolean content; private boolean metadata; diff --git a/rest-model/src/main/java/com/gentics/mesh/core/rest/user/ExpandableNode.java b/rest-model/src/main/java/com/gentics/mesh/core/rest/user/ExpandableNode.java index 4c1d37b03c..3386e7755b 100644 --- a/rest-model/src/main/java/com/gentics/mesh/core/rest/user/ExpandableNode.java +++ b/rest-model/src/main/java/com/gentics/mesh/core/rest/user/ExpandableNode.java @@ -1,9 +1,11 @@ package com.gentics.mesh.core.rest.user; +import com.gentics.mesh.core.rest.common.RestModel; + /** * Marker interface which is used to identify a node field which can be expanded. */ -public interface ExpandableNode { +public interface ExpandableNode extends RestModel { /** * Return the node uuid. diff --git a/rest-model/src/main/java/com/gentics/mesh/core/rest/user/NodeReference.java b/rest-model/src/main/java/com/gentics/mesh/core/rest/user/NodeReference.java index c6e70c5558..1878ecee2c 100644 --- a/rest-model/src/main/java/com/gentics/mesh/core/rest/user/NodeReference.java +++ b/rest-model/src/main/java/com/gentics/mesh/core/rest/user/NodeReference.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyDescription; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.gentics.mesh.core.rest.common.RestModel; import com.gentics.mesh.core.rest.node.NodeResponse; import com.gentics.mesh.core.rest.schema.SchemaReference; import com.gentics.mesh.core.rest.schema.impl.SchemaReferenceImpl; @@ -12,7 +13,7 @@ * A node reference contains the bare minimum of useful information which identifies a node. Various field in the {@link NodeResponse} utilize these references * in order to reduce data. */ -public class NodeReference implements ExpandableNode { +public class NodeReference implements ExpandableNode, RestModel { @JsonProperty(required = true) @JsonPropertyDescription("Name of the project to which the node belongs") diff --git a/rest-model/src/main/java/com/gentics/mesh/json/JsonUtil.java b/rest-model/src/main/java/com/gentics/mesh/json/JsonUtil.java index 9b495f6ab5..65be61a627 100644 --- a/rest-model/src/main/java/com/gentics/mesh/json/JsonUtil.java +++ b/rest-model/src/main/java/com/gentics/mesh/json/JsonUtil.java @@ -6,6 +6,8 @@ import java.io.IOException; import org.codehaus.jettison.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -19,11 +21,14 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver; import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.module.jsonSchema.JsonSchema; import com.fasterxml.jackson.module.jsonSchema.JsonSchemaGenerator; import com.gentics.mesh.core.rest.error.AbstractRestException; import com.gentics.mesh.core.rest.error.GenericRestException; @@ -53,21 +58,19 @@ import com.gentics.mesh.json.deserializer.FieldDeserializer; import com.gentics.mesh.json.deserializer.FieldMapDeserializer; import com.gentics.mesh.json.deserializer.FieldSchemaDeserializer; -import com.gentics.mesh.json.deserializer.JsonArrayDeserializer; -import com.gentics.mesh.json.deserializer.JsonObjectDeserializer; import com.gentics.mesh.json.deserializer.NodeFieldListItemDeserializer; import com.gentics.mesh.json.deserializer.PermissionChangedEventModelDeserializer; import com.gentics.mesh.json.deserializer.RestExceptionDeserializer; import com.gentics.mesh.json.deserializer.UserNodeReferenceDeserializer; import com.gentics.mesh.json.serializer.BasicFieldSerializer; import com.gentics.mesh.json.serializer.FieldListSerializer; -import com.gentics.mesh.json.serializer.JsonArraySerializer; -import com.gentics.mesh.json.serializer.JsonObjectSerializer; +import com.gentics.vertx.openapi.model.serde.JsonArrayDeserializer; +import com.gentics.vertx.openapi.model.serde.JsonArraySerializer; +import com.gentics.vertx.openapi.model.serde.JsonObjectDeserializer; +import com.gentics.vertx.openapi.model.serde.JsonObjectSerializer; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Main JSON Util which is used to register all custom JSON specific handlers and deserializers. @@ -91,8 +94,11 @@ public final class JsonUtil { private static void initDefaultMapper() { minifyingPrettyPrinter = new MinimalPrettyPrinter(); - defaultMapper = new ObjectMapper(new JsonFactoryBuilder() - .streamReadConstraints(StreamReadConstraints.builder().maxStringLength(Integer.MAX_VALUE).build()).build()); + defaultMapper = JsonMapper.builder(new JsonFactoryBuilder() + .streamReadConstraints(StreamReadConstraints.builder().maxStringLength(Integer.MAX_VALUE).build()) + .build()) + .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS) + .build(); defaultMapper.setDefaultPropertyInclusion(JsonInclude.Value.construct(Include.NON_NULL, Include.ALWAYS)); defaultMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); @@ -238,21 +244,46 @@ public static T readValue(String content, Class valueType) throws Generic } /** - * Generate the JSON schema for the given model class. + * Generate the JSON string for the given model schema. * * @param clazz * Model class * @return */ - public static String getJsonSchema(Class clazz) { + public static String getJsonSchema(JsonSchema schema) { try { - com.fasterxml.jackson.module.jsonSchema.JsonSchema schema = schemaGen.generateSchema(clazz); return defaultMapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema); } catch (Exception e) { throw new GenericRestException(INTERNAL_SERVER_ERROR, "error_internal", e); } } + /** + * Generate the JSON schema model for the given model class. + * + * @param clazz + * Model class + * @return + */ + public static String getJsonSchema(Class clazz) { + return getJsonSchema(getJsonSchemaObject(clazz)); + } + + /** + * Generate the JSON schema for the given model class. + * + * @param clazz + * Model class + * @return + */ + public static JsonSchema getJsonSchemaObject(Class clazz) { + try { + return schemaGen.generateSchema(clazz); + } catch (Exception e) { + throw new GenericRestException(INTERNAL_SERVER_ERROR, "error_internal", e); + } + } + /** * Return the JSON object mapper. * diff --git a/rest-model/src/main/java/com/gentics/mesh/json/deserializer/JsonArrayDeserializer.java b/rest-model/src/main/java/com/gentics/mesh/json/deserializer/JsonArrayDeserializer.java deleted file mode 100644 index 0d852818f3..0000000000 --- a/rest-model/src/main/java/com/gentics/mesh/json/deserializer/JsonArrayDeserializer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.gentics.mesh.json.deserializer; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.ObjectCodec; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; - -import io.vertx.core.json.JsonArray; - -/** - * Custom deserializer for Vert.x {@link JsonArray} - */ -public class JsonArrayDeserializer extends JsonDeserializer { - - @Override - public JsonArray deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException { - ObjectCodec oc = jsonParser.getCodec(); - JsonNode node = oc.readTree(jsonParser); - return new JsonArray(node.toString()); - } - -} diff --git a/rest-model/src/main/java/com/gentics/mesh/json/deserializer/JsonObjectDeserializer.java b/rest-model/src/main/java/com/gentics/mesh/json/deserializer/JsonObjectDeserializer.java deleted file mode 100644 index b0b09e10ef..0000000000 --- a/rest-model/src/main/java/com/gentics/mesh/json/deserializer/JsonObjectDeserializer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.gentics.mesh.json.deserializer; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.ObjectCodec; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; - -import io.vertx.core.json.JsonObject; - -/** - * Custom deserializer for {@link JsonObject} - */ -public class JsonObjectDeserializer extends JsonDeserializer { - - @Override - public JsonObject deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException { - ObjectCodec oc = jsonParser.getCodec(); - JsonNode node = oc.readTree(jsonParser); - return new JsonObject(node.toString()); - } - -} diff --git a/rest-model/src/main/java/com/gentics/mesh/json/serializer/JsonArraySerializer.java b/rest-model/src/main/java/com/gentics/mesh/json/serializer/JsonArraySerializer.java deleted file mode 100644 index d7647e3515..0000000000 --- a/rest-model/src/main/java/com/gentics/mesh/json/serializer/JsonArraySerializer.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gentics.mesh.json.serializer; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -import io.vertx.core.json.JsonArray; - -/** - * Custom JSON serializer for Vert.x {@link JsonArray}. - */ -public class JsonArraySerializer extends JsonSerializer { - - @Override - public void serialize(JsonArray value, JsonGenerator jgen, SerializerProvider provider) throws IOException { - jgen.writeObject(value.getList()); - } -} diff --git a/rest-model/src/main/java/com/gentics/mesh/json/serializer/JsonObjectSerializer.java b/rest-model/src/main/java/com/gentics/mesh/json/serializer/JsonObjectSerializer.java deleted file mode 100644 index e6824245fe..0000000000 --- a/rest-model/src/main/java/com/gentics/mesh/json/serializer/JsonObjectSerializer.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.gentics.mesh.json.serializer; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -import io.vertx.core.json.JsonObject; - -/** - * Custom serializer for Vert.x {@link JsonObject} - */ -public class JsonObjectSerializer extends JsonSerializer { - - @Override - public void serialize(JsonObject value, JsonGenerator jgen, SerializerProvider provider) throws IOException { - jgen.writeObject(value.getMap()); - } -} diff --git a/rest-model/src/main/java/com/gentics/mesh/parameter/BackupParameters.java b/rest-model/src/main/java/com/gentics/mesh/parameter/BackupParameters.java index d94d292628..f9b144f295 100644 --- a/rest-model/src/main/java/com/gentics/mesh/parameter/BackupParameters.java +++ b/rest-model/src/main/java/com/gentics/mesh/parameter/BackupParameters.java @@ -26,6 +26,6 @@ default BackupParameters setConsistencyCheck(boolean flag) { * @return */ default boolean isConsistencyCheck() { - return BooleanUtils.toBooleanDefaultIfNull(Boolean.valueOf(getParameter(CONSISTENCY_CHECK_PARAMETER_KEY)), false); + return BooleanUtils.toBooleanDefaultIfNull(BooleanUtils.toBooleanObject(getParameter(CONSISTENCY_CHECK_PARAMETER_KEY)), false); } } diff --git a/rest-model/src/main/java/com/gentics/mesh/parameter/ConsistencyCheckParameters.java b/rest-model/src/main/java/com/gentics/mesh/parameter/ConsistencyCheckParameters.java index 09864656b6..a9e0d2b902 100644 --- a/rest-model/src/main/java/com/gentics/mesh/parameter/ConsistencyCheckParameters.java +++ b/rest-model/src/main/java/com/gentics/mesh/parameter/ConsistencyCheckParameters.java @@ -28,6 +28,6 @@ default ConsistencyCheckParameters setAsync(boolean flag) { * @return flag value */ default boolean isAsync() { - return BooleanUtils.toBooleanDefaultIfNull(Boolean.valueOf(getParameter(ASYNC_PARAMETER_KEY)), false); + return BooleanUtils.toBooleanDefaultIfNull(BooleanUtils.toBooleanObject(getParameter(ASYNC_PARAMETER_KEY)), false); } } diff --git a/rest-model/src/main/java/com/gentics/mesh/parameter/DeleteParameters.java b/rest-model/src/main/java/com/gentics/mesh/parameter/DeleteParameters.java index 6efbde63c7..b5e4a23609 100644 --- a/rest-model/src/main/java/com/gentics/mesh/parameter/DeleteParameters.java +++ b/rest-model/src/main/java/com/gentics/mesh/parameter/DeleteParameters.java @@ -26,6 +26,6 @@ default DeleteParameters setRecursive(boolean flag) { * @return */ default boolean isRecursive() { - return BooleanUtils.toBooleanDefaultIfNull(Boolean.valueOf(getParameter(RECURSIVE_PARAMETER_KEY)), false); + return BooleanUtils.toBooleanDefaultIfNull(BooleanUtils.toBooleanObject(getParameter(RECURSIVE_PARAMETER_KEY)), false); } } diff --git a/rest-model/src/main/java/com/gentics/mesh/parameter/EtagParameters.java b/rest-model/src/main/java/com/gentics/mesh/parameter/EtagParameters.java new file mode 100644 index 0000000000..b73c457940 --- /dev/null +++ b/rest-model/src/main/java/com/gentics/mesh/parameter/EtagParameters.java @@ -0,0 +1,36 @@ +package com.gentics.mesh.parameter; + +/** + * ETAG parameters + */ +public interface EtagParameters extends ParameterProvider { + + /** + * Query parameter key: {@value #ETAG_PARAM_KEY} + */ + public static final String ETAG_PARAM_KEY = "etag"; + + /** + * Return whether the etag should be omitted or included. + * + * @return + */ + default boolean getETag() { + String value = getParameter(ETAG_PARAM_KEY); + if (value != null) { + return Boolean.valueOf(value); + } else { + return true; + } + } + + /** + * Set the etag inclusion flag. + * + * @param includeEtag + */ + default EtagParameters setETag(boolean includeEtag) { + setParameter(ETAG_PARAM_KEY, String.valueOf(includeEtag)); + return this; + } +} diff --git a/rest-model/src/main/java/com/gentics/mesh/parameter/GenericParameters.java b/rest-model/src/main/java/com/gentics/mesh/parameter/GenericParameters.java index a7ca8afa60..a926091f17 100644 --- a/rest-model/src/main/java/com/gentics/mesh/parameter/GenericParameters.java +++ b/rest-model/src/main/java/com/gentics/mesh/parameter/GenericParameters.java @@ -6,18 +6,13 @@ /** * Interface for generic query parameters. */ -public interface GenericParameters extends ParameterProvider { +public interface GenericParameters extends EtagParameters { /** * Query parameter key: {@value #FIELDS_PARAM_KEY} */ public static final String FIELDS_PARAM_KEY = "fields"; - /** - * Query parameter key: {@value #ETAG_PARAM_KEY} - */ - public static final String ETAG_PARAM_KEY = "etag"; - /** * Return the fields which should be included in the response. * @@ -43,27 +38,9 @@ default GenericParameters setFields(String... fields) { return this; } - /** - * Return whether the etag should be omitted or included. - * - * @return - */ - default boolean getETag() { - String value = getParameter(ETAG_PARAM_KEY); - if (value != null) { - return Boolean.valueOf(value); - } else { - return true; - } - } - - /** - * Set the etag inclusion flag. - * - * @param includeEtag - */ + @Override default GenericParameters setETag(boolean includeEtag) { - setParameter(ETAG_PARAM_KEY, String.valueOf(includeEtag)); + EtagParameters.super.setETag(includeEtag); return this; } } diff --git a/rest-model/src/main/java/com/gentics/mesh/parameter/LanguageParameters.java b/rest-model/src/main/java/com/gentics/mesh/parameter/LanguageParameters.java new file mode 100644 index 0000000000..cfa34f543c --- /dev/null +++ b/rest-model/src/main/java/com/gentics/mesh/parameter/LanguageParameters.java @@ -0,0 +1,38 @@ +package com.gentics.mesh.parameter; + +/** + * Language parameters + */ +public interface LanguageParameters extends ParameterProvider { + + /** + * Query parameter key: {@value #LANGUAGES_QUERY_PARAM_KEY} + */ + public static final String LANGUAGES_QUERY_PARAM_KEY = "lang"; + + + /** + * Set the {@value #LANGUAGES_QUERY_PARAM_KEY} request parameter values. + * + * @param languageTags + * @return Fluent API + */ + default LanguageParameters setLanguages(String... languageTags) { + setParameter(LANGUAGES_QUERY_PARAM_KEY, convertToStr(languageTags)); + return this; + } + + /** + * Return the {@value #LANGUAGES_QUERY_PARAM_KEY} request parameter values. + * + * @return + */ + default String[] getLanguages() { + String value = getParameter(LANGUAGES_QUERY_PARAM_KEY); + String[] languages = null; + if (value != null) { + languages = value.split(","); + } + return languages; + } +} diff --git a/rest-model/src/main/java/com/gentics/mesh/parameter/NodeParameters.java b/rest-model/src/main/java/com/gentics/mesh/parameter/NodeParameters.java index 30ee7fba14..0b32dec895 100644 --- a/rest-model/src/main/java/com/gentics/mesh/parameter/NodeParameters.java +++ b/rest-model/src/main/java/com/gentics/mesh/parameter/NodeParameters.java @@ -8,12 +8,7 @@ /** * Interface for node query parameters. */ -public interface NodeParameters extends ParameterProvider { - - /** - * Query parameter key: {@value #LANGUAGES_QUERY_PARAM_KEY} - */ - public static final String LANGUAGES_QUERY_PARAM_KEY = "lang"; +public interface NodeParameters extends LanguageParameters { /** * Query parameter key: {@value #EXPANDFIELDS_QUERY_PARAM_KEY} @@ -36,25 +31,12 @@ public interface NodeParameters extends ParameterProvider { * @param languageTags * @return Fluent API */ + @Override default NodeParameters setLanguages(String... languageTags) { - setParameter(LANGUAGES_QUERY_PARAM_KEY, convertToStr(languageTags)); + LanguageParameters.super.setLanguages(languageTags); return this; } - /** - * Return the {@value #LANGUAGES_QUERY_PARAM_KEY} request parameter values. - * - * @return - */ - default String[] getLanguages() { - String value = getParameter(LANGUAGES_QUERY_PARAM_KEY); - String[] languages = null; - if (value != null) { - languages = value.split(","); - } - return languages; - } - /** * Set the {@value #RESOLVE_LINKS_QUERY_PARAM_KEY} request parameter. * diff --git a/rest-model/src/main/java/com/gentics/mesh/parameter/ParameterProvider.java b/rest-model/src/main/java/com/gentics/mesh/parameter/ParameterProvider.java index ab08130ff8..3d878ae7c0 100644 --- a/rest-model/src/main/java/com/gentics/mesh/parameter/ParameterProvider.java +++ b/rest-model/src/main/java/com/gentics/mesh/parameter/ParameterProvider.java @@ -1,157 +1,8 @@ package com.gentics.mesh.parameter; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.apache.commons.lang.BooleanUtils; -import org.raml.model.parameter.QueryParameter; - /** * Common interface for query parameters. */ -public interface ParameterProvider { - - /** - * * Validate the parameters and throw an exception when an invalid set of parameters has been detected. - */ - default void validate() { - } - - /** - * Return the RAML parameters for this provider. - * - * @return - */ - Map getRAMLParameters(); - - /** - * Set the query parameter. - * - * @param name - * Parameter name - * @param value - * Parameter value - */ - void setParameter(String name, String value); - - /** - * Set the multivalue query parameter - * @param value type - * @param name parameter name - * @param values parameter values - * @param converter function to convert the values into strings - */ - default void setMultivalueParameter(String name, Collection values, Function converter) { - if (values == null) { - setParameter(name, null); - } else { - setParameter(name, values.stream().map(converter::apply).collect(Collectors.joining(","))); - } - } - - /** - * Set the multivalue query parameter to string values - * @param name name - * @param values string values - */ - default void setMultivalueParameter(String name, Collection values) { - setMultivalueParameter(name, values, Function.identity()); - } - - /** - * Return the query parameter value for the given name. - * - * @param name - * Parameter name - * @return Loaded value or null - */ - String getParameter(String name); - - /** - * Return the query parameter values for the given name. - * @param value type - * @param name parameter name - * @param converter function that converts the stores String into the expected value - * @return Loaded values or empty set - */ - default Set getMultivalueParameter(String name, Function converter) { - String value = getParameter(name); - if (value == null || value.isEmpty()) { - return Collections.emptySet(); - } else { - return Arrays.asList(value.split(",")).stream().map(converter::apply).collect(Collectors.toSet()); - } - } - - /** - * Return the query parameter values for the given name as set of strings - * @param name parameter name - * @return Loaded values or empty set - */ - default Set getMultivalueParameter(String name) { - return getMultivalueParameter(name, Function.identity()); - } - - /** - * Return the query parameters as a map. - * - * @return - */ - Map getParameters(); - - /** - * Convert the provides object to a string representation. - * - * @param value - * @return String representation of value - */ - default String convertToStr(Object value) { - if (value instanceof String[]) { - String stringVal = ""; - String[] values = (String[]) value; - for (int i = 0; i < values.length; i++) { - stringVal += values[i]; - if (i != values.length - 1) { - stringVal += ','; - } - } - return stringVal; - } else if (value instanceof Integer) { - return Integer.toString((int) value); - } else if (value instanceof Boolean) { - return BooleanUtils.toStringTrueFalse((Boolean) value); - } else { - return value.toString(); - } - } - - /** - * Return the query parameters which do not include the the first & or ? character. - * - * @return Query string - */ - default String getQueryParameters() { - StringBuilder query = new StringBuilder(); - Map params = getParameters(); - for (Entry entry : params.entrySet()) { - String value = entry.getValue(); - if (value != null) { - if (query.length() != 0) { - query.append("&"); - } - // try { - query.append(entry.getKey() + "=" + value);// URLEncoder.encode(value, "UTF-8")); - // } catch (UnsupportedEncodingException e) { - // } - } - } - return query.toString(); - } +public interface ParameterProvider extends com.gentics.vertx.openapi.model.ParameterProvider { } diff --git a/rest-model/src/main/java/com/gentics/mesh/parameter/PublishParameters.java b/rest-model/src/main/java/com/gentics/mesh/parameter/PublishParameters.java index 7587d61098..c3aefc34b6 100644 --- a/rest-model/src/main/java/com/gentics/mesh/parameter/PublishParameters.java +++ b/rest-model/src/main/java/com/gentics/mesh/parameter/PublishParameters.java @@ -27,7 +27,7 @@ default PublishParameters setRecursive(boolean flag) { */ default boolean isRecursive() { - return BooleanUtils.toBooleanDefaultIfNull(Boolean.valueOf(getParameter(RECURSIVE_PARAMETER_KEY)), false); + return BooleanUtils.toBooleanDefaultIfNull(BooleanUtils.toBooleanObject(getParameter(RECURSIVE_PARAMETER_KEY)), false); } } diff --git a/rest-model/src/main/java/com/gentics/mesh/parameter/SchemaUpdateParameters.java b/rest-model/src/main/java/com/gentics/mesh/parameter/SchemaUpdateParameters.java index 40b0db2c16..ff14ddf385 100644 --- a/rest-model/src/main/java/com/gentics/mesh/parameter/SchemaUpdateParameters.java +++ b/rest-model/src/main/java/com/gentics/mesh/parameter/SchemaUpdateParameters.java @@ -91,7 +91,7 @@ default SchemaUpdateParameters setStrictValidation(boolean flag) { * @return */ default boolean isStrictValidation() { - return BooleanUtils.toBooleanDefaultIfNull(Boolean.valueOf(getParameter(STRICT_VALIDATION_KEY)), false); + return BooleanUtils.toBooleanDefaultIfNull(BooleanUtils.toBooleanObject(getParameter(STRICT_VALIDATION_KEY)), false); } } diff --git a/rest-model/src/main/java/com/gentics/mesh/parameter/image/ImageRect.java b/rest-model/src/main/java/com/gentics/mesh/parameter/image/ImageRect.java index 607fceb6c6..d5e90c9b6f 100644 --- a/rest-model/src/main/java/com/gentics/mesh/parameter/image/ImageRect.java +++ b/rest-model/src/main/java/com/gentics/mesh/parameter/image/ImageRect.java @@ -6,12 +6,13 @@ import java.util.Objects; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.gentics.mesh.core.rest.common.RestModel; import com.gentics.mesh.parameter.ImageManipulationParameters; /** * Class which represents an image rectangular. */ -public class ImageRect { +public class ImageRect implements RestModel { private int startX; private int startY; diff --git a/tests/common/src/main/java/com/gentics/mesh/test/ClientHelper.java b/tests/common/src/main/java/com/gentics/mesh/test/ClientHelper.java index 7b9b920cb6..3dc401bc24 100644 --- a/tests/common/src/main/java/com/gentics/mesh/test/ClientHelper.java +++ b/tests/common/src/main/java/com/gentics/mesh/test/ClientHelper.java @@ -10,6 +10,8 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; import java.util.Locale; import java.util.Objects; import java.util.concurrent.TimeUnit; @@ -18,6 +20,7 @@ import com.gentics.mesh.core.data.i18n.I18NUtil; import com.gentics.mesh.core.rest.common.GenericMessageResponse; import com.gentics.mesh.core.rest.error.GenericRestException; +import com.gentics.mesh.json.JsonUtil; import com.gentics.mesh.rest.client.MeshRequest; import com.gentics.mesh.rest.client.MeshResponse; import com.gentics.mesh.rest.client.MeshRestClientMessageException; @@ -25,6 +28,7 @@ import com.gentics.mesh.test.context.ClientHandler; import com.gentics.mesh.test.util.TestUtils; import com.gentics.mesh.util.ETag; +import com.google.gson.JsonSyntaxException; import io.netty.handler.codec.http.HttpResponseStatus; import io.reactivex.Observable; @@ -159,6 +163,17 @@ public static MeshRestClientMessageException call(ClientHandler handler, Throwable cause = e.getCause(); if (cause instanceof MeshRestClientMessageException) { error = (MeshRestClientMessageException) e.getCause(); + } else if (cause.getClass().getCanonicalName().equals("org.openapitools.client.ApiException")) { + try { + String responseBody = (String) Arrays.stream(cause.getClass().getDeclaredMethods()).filter(m -> m.getName().equals("getResponseBody") && m.getParameterCount() == 0).findAny().orElseThrow(() -> new IllegalStateException(e)).invoke(cause); + int code = (int) Arrays.stream(cause.getClass().getDeclaredMethods()).filter(m -> m.getName().equals("getCode") && m.getParameterCount() == 0).findAny().orElseThrow(() -> new IllegalStateException(e)).invoke(cause); + String message = (String) Arrays.stream(cause.getClass().getDeclaredMethods()).filter(m -> m.getName().equals("getMessage") && m.getParameterCount() == 0).findAny().orElseThrow(() -> new IllegalStateException(e)).invoke(cause); + error = new MeshRestClientMessageException(code, message, JsonUtil.readValue(responseBody, GenericMessageResponse.class), null, null); + } catch (JsonSyntaxException | GenericRestException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException | IllegalStateException + | SecurityException e1) { + throw new RuntimeException(e1); + } } else { throw (RuntimeException) e; } @@ -170,9 +185,7 @@ public static MeshRestClientMessageException call(ClientHandler handler, } else { expectException(error, status, bodyMessageI18nKey, i18nParams); } - if (error instanceof MeshRestClientMessageException) { - return (MeshRestClientMessageException) e.getCause(); - } + return error; } catch (Exception e) { throw new RuntimeException(e); } diff --git a/tests/common/src/main/java/com/gentics/mesh/test/context/MeshTestContext.java b/tests/common/src/main/java/com/gentics/mesh/test/context/MeshTestContext.java index 074b2a0e59..eec8b39796 100644 --- a/tests/common/src/main/java/com/gentics/mesh/test/context/MeshTestContext.java +++ b/tests/common/src/main/java/com/gentics/mesh/test/context/MeshTestContext.java @@ -8,6 +8,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.nio.file.NoSuchFileException; import java.security.cert.CertificateException; import java.time.Duration; @@ -72,7 +73,6 @@ import com.gentics.mesh.search.TrackingSearchProvider; import com.gentics.mesh.search.TrackingSearchProviderImpl; import com.gentics.mesh.search.verticle.ElasticsearchProcessVerticle; -import com.gentics.mesh.test.ElasticsearchTestMode; import com.gentics.mesh.test.MeshCoreOptionChanger; import com.gentics.mesh.test.MeshInstanceProvider; import com.gentics.mesh.test.MeshTestActions; @@ -1020,6 +1020,20 @@ public Mesh getMesh() { return mesh; } + private MeshRestClient createRestClient(MeshRestClientConfig config) { + String customMeshRestClient = System.getenv("MESH_REST_CLIENT_CLASS"); + if (StringUtils.isNotBlank(customMeshRestClient)) { + try { + return (MeshRestClient) Class.forName(customMeshRestClient).getConstructor(MeshRestClientConfig.class, OkHttpClient.class).newInstance(config, okHttp); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException | NoSuchMethodException | SecurityException + | ClassNotFoundException e) { + LOG.error("Could not instantiate MeshRestClient from class " + customMeshRestClient, e); + } + } + return MeshRestClient.create(config, okHttp); + } + private void setupRestEndpoints(MeshTestSetting settings) throws Exception { mesh.getOptions().getUploadOptions().setByteLimit(Long.MAX_VALUE); @@ -1034,11 +1048,11 @@ private void setupRestEndpoints(MeshTestSetting settings) throws Exception { .setBasePath(CURRENT_API_BASE_PATH) .setSsl(false); - MeshRestClient httpClient = MeshRestClient.create(httpConfigBuilder.build(), okHttp); + MeshRestClient httpClient = createRestClient(httpConfigBuilder.build()); httpClient.setLogin(getData().user().getUsername(), getData().getUserInfo().getPassword()); httpClient.login().blockingGet(); clients.put("http_v" + CURRENT_API_VERSION, httpClient); - anonymousClients.put("http_v" + CURRENT_API_VERSION, MeshRestClient.create(httpConfigBuilder.build(), okHttp)); + anonymousClients.put("http_v" + CURRENT_API_VERSION, createRestClient(httpConfigBuilder.build())); // Setup SSL client if needed SSLTestMode ssl = settings.ssl(); diff --git a/tests/tests-core/pom.xml b/tests/tests-core/pom.xml index 8dd04042c0..1f95f9ec7e 100644 --- a/tests/tests-core/pom.xml +++ b/tests/tests-core/pom.xml @@ -24,6 +24,12 @@ com.gentics.mesh tests-mesh-common + + + com.github.java-json-tools + json-schema-validator + + com.gentics.mesh @@ -79,12 +85,46 @@ org.mock-server mockserver-junit-rule 5.9.0 + + + com.github.java-json-tools + json-schema-validator + + + + + com.github.java-json-tools + json-schema-validator + 2.2.14 org.apache.httpcomponents httpcore 4.4.13 + + io.swagger.parser.v3 + swagger-parser + 2.1.39 + + + jakarta.annotation + jakarta.annotation-api + 2.1.1 + + + com.google.code.gson + gson + + + io.gsonfire + gson-fire + 1.9.0 + + + com.squareup.okhttp3 + logging-interceptor + @@ -103,6 +143,29 @@ + + org.codehaus.mojo + exec-maven-plugin + 1.5.0 + + + Generate OpenAPI + + exec + + generate-resources + + ${env.JAVA_HOME}/bin/java + + -classpath + + com.gentics.mesh.generator.runner.OpenAPISpecGeneratorRunner + ${basedir}/../../doc/src/main/docs/generated + + + + + maven-invoker-plugin 3.1.0 @@ -135,6 +198,57 @@ + + org.openapitools + openapi-generator-maven-plugin + 7.19.0 + + + generate-client + + generate + + process-resources + + ${basedir}/../../doc/src/main/docs/generated/api/openapi.yaml + ${project.build.directory}/generated-sources/openapi + java + false + false + true + false + + true + true + false + true + / + false + + okhttp-gson + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-sources + generate-sources + + add-source + + + + ${project.build.directory}/generated-sources/openapi + ${project.build.directory}/generated-sources/annotations + + + + + diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/cli/MeshIntegerationTest.java b/tests/tests-core/src/main/java/com/gentics/mesh/cli/MeshIntegerationTest.java index bbc9acfcd2..0ca9b86613 100644 --- a/tests/tests-core/src/main/java/com/gentics/mesh/cli/MeshIntegerationTest.java +++ b/tests/tests-core/src/main/java/com/gentics/mesh/cli/MeshIntegerationTest.java @@ -7,6 +7,7 @@ import org.apache.commons.io.FileUtils; import org.junit.Before; import org.junit.FixMethodOrder; +import org.junit.Ignore; import org.junit.Test; import org.junit.runners.MethodSorters; @@ -28,6 +29,7 @@ public void cleanup() throws IOException { } @Test + @Ignore("Makes nothing but heavy runtime load") public void testStartup() throws Exception { MeshOptions options = getOptions(); Mesh mesh = Mesh.create(options); diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/client/MeshRestClientTokenTest.java b/tests/tests-core/src/main/java/com/gentics/mesh/client/MeshRestClientTokenTest.java index e21902f8d4..5697d9c571 100644 --- a/tests/tests-core/src/main/java/com/gentics/mesh/client/MeshRestClientTokenTest.java +++ b/tests/tests-core/src/main/java/com/gentics/mesh/client/MeshRestClientTokenTest.java @@ -4,14 +4,19 @@ import static com.gentics.mesh.test.ClientHelper.call; import static com.gentics.mesh.test.ElasticsearchTestMode.NONE; import static com.gentics.mesh.test.TestSize.PROJECT; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Consumer; import org.junit.Before; import org.junit.Test; import com.gentics.mesh.demo.UserInfo; import com.gentics.mesh.etc.config.MeshOptions; +import com.gentics.mesh.rest.client.MeshRestClientMessageException; import com.gentics.mesh.test.MeshOptionChanger; import com.gentics.mesh.test.MeshTestSetting; import com.gentics.mesh.test.TestDataProvider; @@ -67,13 +72,34 @@ public void setUp() throws Exception { public void testLogin() throws Exception { client().setLogin(username, password).login().blockingGet(); - // now get "me" for 10 seconds (once every second). This will fail, when the token expires - Flowable.intervalRange(0, 10, 0, 1, TimeUnit.SECONDS).flatMapSingle(v -> { - return client().me().toSingle(); - }).doOnNext(response -> { - // assert that we still are the correct user - assertThat(response).hasName(username); - }).blockingSubscribe(); + AtomicLong startAt = new AtomicLong(System.currentTimeMillis()); + try { + // now get "me" for 10 seconds (once every second). This will fail in 5 (TOKEN_EXPIRATION_TIME_SECONDS), when the token expires + Flowable.intervalRange(0, 10, 0, 1, TimeUnit.SECONDS).flatMapSingle(v -> { + return client().me().toSingle(); + }).doOnError(t -> { + // assert the expired token + assertThat((System.currentTimeMillis() - startAt.get())).as("Token expiration time").isGreaterThan(TOKEN_EXPIRATION_TIME_SECONDS * 1000); + Consumer assertException = tt -> { + assertThat(tt.getStatusCode()).as("REST client error status").isEqualTo(401); + }; + if (t instanceof MeshRestClientMessageException tt) { + assertException.accept(tt); + } else if (t.getCause() instanceof MeshRestClientMessageException tt) { + assertException.accept(tt); + } else { + fail(t); + } + }).doOnNext(response -> { + // assert that we still are the correct user + assertThat(response).hasName(username); + // assert the inexpired token + assertThat((System.currentTimeMillis() - startAt.get())).as("Token expiration time").isLessThanOrEqualTo(TOKEN_EXPIRATION_TIME_SECONDS * 1000); + }).blockingSubscribe(); + } catch (Exception e) { + e.printStackTrace(); + // already asserted + } } /** diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/core/group/GroupEndpointTest.java b/tests/tests-core/src/main/java/com/gentics/mesh/core/group/GroupEndpointTest.java index a219525990..30ff5c4076 100644 --- a/tests/tests-core/src/main/java/com/gentics/mesh/core/group/GroupEndpointTest.java +++ b/tests/tests-core/src/main/java/com/gentics/mesh/core/group/GroupEndpointTest.java @@ -113,9 +113,9 @@ public void testCreateWithUuid() throws Exception { final String name = "New Name"; String uuid = UUIDUtil.randomUUID(); - GroupUpdateRequest request = new GroupUpdateRequest(); + GroupCreateRequest request = new GroupCreateRequest(); request.setName(name); - GroupResponse restGroup = call(() -> client().updateGroup(uuid, request)); + GroupResponse restGroup = call(() -> client().createGroup(uuid, request)); waitForSearchIdleEvent(); diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/core/openapi/OpenAPIEndpointTest.java b/tests/tests-core/src/main/java/com/gentics/mesh/core/openapi/OpenAPIEndpointTest.java new file mode 100644 index 0000000000..e5ce5e7299 --- /dev/null +++ b/tests/tests-core/src/main/java/com/gentics/mesh/core/openapi/OpenAPIEndpointTest.java @@ -0,0 +1,94 @@ +package com.gentics.mesh.core.openapi; + +import static com.gentics.mesh.test.ClientHelper.call; +import static com.gentics.mesh.test.TestSize.FULL; +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +import com.gentics.mesh.MeshVersion; +import com.gentics.mesh.test.MeshTestSetting; +import com.gentics.mesh.test.context.AbstractMeshTest; + +import io.netty.handler.codec.http.HttpResponseStatus; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.parser.OpenAPIV3Parser; +import io.swagger.v3.parser.core.models.ParseOptions; +import io.swagger.v3.parser.core.models.SwaggerParseResult; + +@MeshTestSetting(testSize = FULL, startServer = true) +@RunWith(Parameterized.class) +public class OpenAPIEndpointTest extends AbstractMeshTest { + + @Parameters(name = "{index}: no Mesh Client = {0}, OpenAPI disabled: {1}") + public static Collection parameters() throws Exception { + List params = new ArrayList<>(); + for (boolean noClient : new Boolean[] {false, true}) { + for (boolean apiDisabled : new Boolean[] {false, true}) { + params.add(new Object[] {noClient, apiDisabled}); + } + } + return params; + } + + @Parameter(0) + public boolean noClient; + + @Parameter(1) + public boolean apiDisabled; + + @Before + public void setup() { + testContext.getOptions().setServeOpenApi(!apiDisabled); + } + + @Test + public void testOpenAPI() throws IOException { + String input = null; + if (noClient) { + input = "http://localhost:" + + options().getHttpServerOptions().getPort() + + MeshVersion.CURRENT_API_BASE_PATH + + "/openapi.yaml"; + } else { + grantAdmin(); + if (apiDisabled) { + call(() -> client().getOpenAPI(), HttpResponseStatus.FORBIDDEN); + return; + } else { + input = call(() -> client().getOpenAPI()); + } + } + assertNoErrors(input); + } + + protected OpenAPI assertNoErrors(String input) { + OpenAPIV3Parser parser = new OpenAPIV3Parser(); + ParseOptions options = new ParseOptions(); + options.setResolve(true); + options.setResolveFully(true); + + SwaggerParseResult result = noClient + ? parser.readLocation(input, null, options) + : parser.readContents(input, null, options); + + if (apiDisabled) { + assertThat(result.getOpenAPI()).as("Parsed API").isNull(); + assertThat(result.getMessages()).as("Error messages").isNotEmpty(); + } else { + assertThat(result.getOpenAPI()).as("Parsed API").isNotNull(); + assertThat(result.getMessages()).as("Error messages").isNullOrEmpty(); + } + return result.getOpenAPI(); + } +} diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/plugin/BackupPlugin.java b/tests/tests-core/src/main/java/com/gentics/mesh/plugin/BackupPlugin.java deleted file mode 100644 index 776e08d59e..0000000000 --- a/tests/tests-core/src/main/java/com/gentics/mesh/plugin/BackupPlugin.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.gentics.mesh.plugin; - -import static com.gentics.mesh.core.rest.MeshEvent.CLUSTER_DATABASE_CHANGE_STATUS; - -import java.time.Duration; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.pf4j.PluginWrapper; - -import com.gentics.mesh.RestAPIVersion; -import com.gentics.mesh.plugin.env.PluginEnvironment; -import com.gentics.mesh.rest.client.MeshRestClient; -import com.gentics.mesh.rest.client.MeshRestClientConfig; - -import io.reactivex.Completable; -import io.vertx.core.eventbus.MessageConsumer; -import okhttp3.OkHttpClient; - -/** - * Test plugin which will - *
    - *
  1. Invoke the db backup and fail immediately, when initialized the first time
  2. - *
  3. Succeed initialization for every further attempt
  4. - *
- */ -public class BackupPlugin extends AbstractPlugin { - protected static AtomicBoolean firstStart = new AtomicBoolean(true); - - /** - * Create instance - * @param wrapper plugin wrapper - * @param env environment - */ - public BackupPlugin(PluginWrapper wrapper, PluginEnvironment env) { - super(wrapper, env); - } - - @Override - public Completable initialize() { - if (firstStart.getAndSet(false)) { - return invokeBackupAndFail(); - } else { - return Completable.complete(); - } - } - - /** - * Invoke the db back (using a client with timeout set to 1 ms), wait for the CLUSTER_DATABASE_CHANGE_STATUS event and then fail - * @return failing completable - */ - protected Completable invokeBackupAndFail() { - OkHttpClient okHttpClient = new OkHttpClient.Builder() - .callTimeout(Duration.ofMillis(1)) - .connectTimeout(Duration.ofMillis(1)) - .writeTimeout(Duration.ofMillis(1)) - .readTimeout(Duration.ofMillis(1)) - .build(); - - int port = environment().options().getHttpServerOptions().getPort(); - String host = "127.0.0.1"; - MeshRestClient client = MeshRestClient.create(MeshRestClientConfig.newConfig() - .setPort(port) - .setHost(host) - .setBasePath(RestAPIVersion.V1.getBasePath()) - .build(), okHttpClient); - - client.setAPIKey(environment().adminToken()); - - return client.invokeBackup().toCompletable().onErrorResumeNext(t -> waitForEvent(10_000)) - .andThen(Completable.error(new RuntimeException())); - } - - /** - * Wait for the event CLUSTER_DATABASE_CHANGE_STATUS - * @param timeoutMs timeout - * @return completable - */ - protected Completable waitForEvent(int timeoutMs) { - return Completable.fromAction(() -> { - CountDownLatch latch = new CountDownLatch(1); - MessageConsumer consumer = vertx().eventBus().consumer(CLUSTER_DATABASE_CHANGE_STATUS.address); - consumer.handler(msg -> latch.countDown()); - // The completion handler will be invoked once the consumer has been registered - consumer.completion().andThen(res -> { - if (res.failed()) { - throw new RuntimeException("Could not listen to event", res.cause()); - } - }); - try { - if (!latch.await(timeoutMs, TimeUnit.MILLISECONDS)) { - throw new RuntimeException("Timeout while waiting for event"); - } - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - consumer.unregister(); - }); - } -} diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/test/AbstractIntegrationTest.java b/tests/tests-core/src/main/java/com/gentics/mesh/test/AbstractIntegrationTest.java index b1edaa4ebe..289f2eb15c 100644 --- a/tests/tests-core/src/main/java/com/gentics/mesh/test/AbstractIntegrationTest.java +++ b/tests/tests-core/src/main/java/com/gentics/mesh/test/AbstractIntegrationTest.java @@ -5,4 +5,5 @@ public class AbstractIntegrationTest { * Timeout of {@value #DEFAULT_TIMEOUT_SECONDS} seconds. */ protected static final long DEFAULT_TIMEOUT_SECONDS = 45; + } diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/OpenAPIMeshRawRequestImpl.java b/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/OpenAPIMeshRawRequestImpl.java new file mode 100644 index 0000000000..94ef335a84 --- /dev/null +++ b/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/OpenAPIMeshRawRequestImpl.java @@ -0,0 +1,32 @@ +package com.gentics.mesh.test.openapi; + +import com.gentics.mesh.rest.client.impl.AbstractMeshOkHttpRequest; + +import okhttp3.Call; +import okhttp3.OkHttpClient; +import okhttp3.Request; + +public class OpenAPIMeshRawRequestImpl extends AbstractMeshOkHttpRequest { + + private final UpgradedCall call; + + public OpenAPIMeshRawRequestImpl(OkHttpClient client, UpgradedCall call, Class targetType) { + super(client, targetType); + this.call = call; + } + + @Override + public void setHeader(String name, String value) { + call.getBuilder().header(name, value); + } + + @Override + protected Request createRequest() { + return call.build(); + } + + @Override + protected Call createCall() { + return call; + } +} diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/OpenAPIMeshRequestImpl.java b/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/OpenAPIMeshRequestImpl.java new file mode 100644 index 0000000000..1c1d8f9b35 --- /dev/null +++ b/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/OpenAPIMeshRequestImpl.java @@ -0,0 +1,94 @@ +package com.gentics.mesh.test.openapi; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.function.Function; + +import org.openapitools.client.ApiResponse; +import org.openapitools.client.JSON; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.gentics.mesh.json.JsonUtil; +import com.gentics.mesh.rest.client.MeshRequest; +import com.gentics.mesh.rest.client.MeshResponse; +import com.gentics.mesh.rest.client.impl.EmptyResponse; + +import io.reactivex.Single; + +class OpenAPIMeshRequestImpl implements MeshRequest { + + protected static final Logger log = LoggerFactory.getLogger(OpenAPIMeshRequestImpl.class); + + private final Callable> callable; + private final Class targetType; + + public OpenAPIMeshRequestImpl(Callable> callable, Class targetType) { + this.callable = callable; + this.targetType = targetType; + } + + protected Single> toApiSingle() { + return Single.fromCallable(callable); + } + + @Override + public Single toSingle() { + return toApiSingle().map(apir -> ifNull(apir.getData(), r -> adaptResponse(r))); + } + + @Override + public void setHeader(String name, String value) { + log.warn("Setting custom headers is not supported. Call of " + name + "=" + value + "is ignored"); + } + + @Override + public Single> getResponse() { + return toApiSingle().map(apir -> { + return new MeshResponse() { + + @Override + public Map> getHeaders() { + return apir.getHeaders(); + } + + @Override + public int getStatusCode() { + return apir.getStatusCode(); + } + + @Override + public String getBodyAsString() { + return JsonUtil.toJson(apir.getData()); + } + + @Override + public R getBody() { + return adaptResponse(apir.getData()); + } + + @Override + public void close() { + } + }; + }); + } + + @SuppressWarnings("unchecked") + protected R ifNull(T t, Function ifNotNull) { + if (t == null) { + if (targetType.equals(EmptyResponse.class)) { + return (R) EmptyResponse.getInstance(); + } else { + return null; + } + } else { + return ifNotNull.apply(t); + } + } + + protected R adaptResponse(T t) { + return ifNull(t, r -> JsonUtil.readValue(JSON.getGson().toJson(t), targetType)); + } +} diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/OpenAPIMeshRestClient.java b/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/OpenAPIMeshRestClient.java new file mode 100644 index 0000000000..799332f6da --- /dev/null +++ b/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/OpenAPIMeshRestClient.java @@ -0,0 +1,2184 @@ +package com.gentics.mesh.test.openapi; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.apache.commons.io.FileUtils; +import org.openapitools.client.ApiException; +import org.openapitools.client.JSON; +import org.openapitools.client.model.LoginRequest; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.gentics.mesh.core.rest.MeshServerInfoModel; +import com.gentics.mesh.core.rest.admin.cluster.ClusterStatusResponse; +import com.gentics.mesh.core.rest.admin.cluster.coordinator.CoordinatorMasterResponse; +import com.gentics.mesh.core.rest.admin.consistency.ConsistencyCheckResponse; +import com.gentics.mesh.core.rest.admin.localconfig.LocalConfigModel; +import com.gentics.mesh.core.rest.admin.status.MeshStatusResponse; +import com.gentics.mesh.core.rest.branch.BranchCreateRequest; +import com.gentics.mesh.core.rest.branch.BranchListResponse; +import com.gentics.mesh.core.rest.branch.BranchResponse; +import com.gentics.mesh.core.rest.branch.BranchUpdateRequest; +import com.gentics.mesh.core.rest.branch.info.BranchInfoMicroschemaList; +import com.gentics.mesh.core.rest.branch.info.BranchInfoSchemaList; +import com.gentics.mesh.core.rest.common.GenericMessageResponse; +import com.gentics.mesh.core.rest.common.ObjectPermissionGrantRequest; +import com.gentics.mesh.core.rest.common.ObjectPermissionResponse; +import com.gentics.mesh.core.rest.common.ObjectPermissionRevokeRequest; +import com.gentics.mesh.core.rest.common.RestModel; +import com.gentics.mesh.core.rest.graphql.GraphQLRequest; +import com.gentics.mesh.core.rest.graphql.GraphQLResponse; +import com.gentics.mesh.core.rest.group.GroupCreateRequest; +import com.gentics.mesh.core.rest.group.GroupListResponse; +import com.gentics.mesh.core.rest.group.GroupResponse; +import com.gentics.mesh.core.rest.group.GroupUpdateRequest; +import com.gentics.mesh.core.rest.job.JobListResponse; +import com.gentics.mesh.core.rest.job.JobResponse; +import com.gentics.mesh.core.rest.lang.LanguageListResponse; +import com.gentics.mesh.core.rest.lang.LanguageResponse; +import com.gentics.mesh.core.rest.microschema.impl.MicroschemaCreateRequest; +import com.gentics.mesh.core.rest.microschema.impl.MicroschemaResponse; +import com.gentics.mesh.core.rest.microschema.impl.MicroschemaUpdateRequest; +import com.gentics.mesh.core.rest.navigation.NavigationResponse; +import com.gentics.mesh.core.rest.node.BinaryCheckUpdateRequest; +import com.gentics.mesh.core.rest.node.NodeCreateRequest; +import com.gentics.mesh.core.rest.node.NodeListResponse; +import com.gentics.mesh.core.rest.node.NodeResponse; +import com.gentics.mesh.core.rest.node.NodeUpdateRequest; +import com.gentics.mesh.core.rest.node.NodeUpsertRequest; +import com.gentics.mesh.core.rest.node.PublishStatusModel; +import com.gentics.mesh.core.rest.node.PublishStatusResponse; +import com.gentics.mesh.core.rest.node.field.BinaryCheckStatus; +import com.gentics.mesh.core.rest.node.field.BinaryFieldTransformRequest; +import com.gentics.mesh.core.rest.node.field.image.ImageManipulationRequest; +import com.gentics.mesh.core.rest.node.field.image.ImageVariantsResponse; +import com.gentics.mesh.core.rest.node.field.s3binary.S3BinaryMetadataRequest; +import com.gentics.mesh.core.rest.node.field.s3binary.S3BinaryUploadRequest; +import com.gentics.mesh.core.rest.node.field.s3binary.S3RestResponse; +import com.gentics.mesh.core.rest.node.version.NodeVersionsResponse; +import com.gentics.mesh.core.rest.plugin.PluginDeploymentRequest; +import com.gentics.mesh.core.rest.plugin.PluginListResponse; +import com.gentics.mesh.core.rest.plugin.PluginResponse; +import com.gentics.mesh.core.rest.project.ProjectCreateRequest; +import com.gentics.mesh.core.rest.project.ProjectListResponse; +import com.gentics.mesh.core.rest.project.ProjectResponse; +import com.gentics.mesh.core.rest.project.ProjectUpdateRequest; +import com.gentics.mesh.core.rest.role.RoleCreateRequest; +import com.gentics.mesh.core.rest.role.RoleListResponse; +import com.gentics.mesh.core.rest.role.RolePermissionRequest; +import com.gentics.mesh.core.rest.role.RolePermissionResponse; +import com.gentics.mesh.core.rest.role.RoleResponse; +import com.gentics.mesh.core.rest.role.RoleUpdateRequest; +import com.gentics.mesh.core.rest.schema.MicroschemaListResponse; +import com.gentics.mesh.core.rest.schema.MicroschemaModel; +import com.gentics.mesh.core.rest.schema.MicroschemaReference; +import com.gentics.mesh.core.rest.schema.SchemaListResponse; +import com.gentics.mesh.core.rest.schema.SchemaModel; +import com.gentics.mesh.core.rest.schema.SchemaReference; +import com.gentics.mesh.core.rest.schema.change.impl.SchemaChangesListModel; +import com.gentics.mesh.core.rest.schema.impl.SchemaCreateRequest; +import com.gentics.mesh.core.rest.schema.impl.SchemaResponse; +import com.gentics.mesh.core.rest.schema.impl.SchemaUpdateRequest; +import com.gentics.mesh.core.rest.search.SearchStatusResponse; +import com.gentics.mesh.core.rest.tag.TagCreateRequest; +import com.gentics.mesh.core.rest.tag.TagFamilyCreateRequest; +import com.gentics.mesh.core.rest.tag.TagFamilyListResponse; +import com.gentics.mesh.core.rest.tag.TagFamilyResponse; +import com.gentics.mesh.core.rest.tag.TagFamilyUpdateRequest; +import com.gentics.mesh.core.rest.tag.TagListResponse; +import com.gentics.mesh.core.rest.tag.TagListUpdateRequest; +import com.gentics.mesh.core.rest.tag.TagResponse; +import com.gentics.mesh.core.rest.tag.TagUpdateRequest; +import com.gentics.mesh.core.rest.user.UserAPITokenResponse; +import com.gentics.mesh.core.rest.user.UserCreateRequest; +import com.gentics.mesh.core.rest.user.UserListResponse; +import com.gentics.mesh.core.rest.user.UserPermissionResponse; +import com.gentics.mesh.core.rest.user.UserResetTokenResponse; +import com.gentics.mesh.core.rest.user.UserResponse; +import com.gentics.mesh.core.rest.user.UserUpdateRequest; +import com.gentics.mesh.core.rest.validation.SchemaValidationResponse; +import com.gentics.mesh.parameter.BranchParameters; +import com.gentics.mesh.parameter.ConsistencyCheckParameters; +import com.gentics.mesh.parameter.DeleteParameters; +import com.gentics.mesh.parameter.EtagParameters; +import com.gentics.mesh.parameter.GenericParameters; +import com.gentics.mesh.parameter.ImageManipulationParameters; +import com.gentics.mesh.parameter.ImageManipulationRetrievalParameters; +import com.gentics.mesh.parameter.IndexMaintenanceParameters; +import com.gentics.mesh.parameter.JobParameters; +import com.gentics.mesh.parameter.NavigationParameters; +import com.gentics.mesh.parameter.NodeParameters; +import com.gentics.mesh.parameter.PagingParameters; +import com.gentics.mesh.parameter.ParameterProvider; +import com.gentics.mesh.parameter.ProjectLoadParameters; +import com.gentics.mesh.parameter.PublishParameters; +import com.gentics.mesh.parameter.RolePermissionParameters; +import com.gentics.mesh.parameter.SchemaUpdateParameters; +import com.gentics.mesh.parameter.SearchParameters; +import com.gentics.mesh.parameter.SortingParameters; +import com.gentics.mesh.parameter.VersioningParameters; +import com.gentics.mesh.rest.JWTAuthentication; +import com.gentics.mesh.rest.client.MeshBinaryResponse; +import com.gentics.mesh.rest.client.MeshRequest; +import com.gentics.mesh.rest.client.MeshRestClient; +import com.gentics.mesh.rest.client.MeshRestClientConfig; +import com.gentics.mesh.rest.client.MeshWebrootFieldResponse; +import com.gentics.mesh.rest.client.MeshWebrootResponse; +import com.gentics.mesh.rest.client.MeshWebsocket; +import com.gentics.mesh.rest.client.impl.EmptyResponse; +import com.google.gson.JsonSyntaxException; + +import io.reactivex.Single; +import io.vertx.core.json.JsonObject; +import okhttp3.OkHttpClient; + +/** + * Generated OpenAPI test client adapter. + */ +@SuppressWarnings({"unchecked","rawtypes"}) +public class OpenAPIMeshRestClient implements MeshRestClient { + + private final UpgradedApiClient apiClient; + private final UpgradedDefaultApi api; + private final MeshRestClientConfig config; + private JWTAuthentication authentication = new JWTAuthentication(); + + /** + * Find the parameter in the providers. + * + * @param + * @param key + * @param parameters + * @return + */ + protected static final T findParameter(String key, ParameterProvider... parameters) { + return findParameter(key, false, parameters); + } + + /** + * Find the parameter in the providers. + * + * @param + * @param key + * @param forceString do not cast to the desired type + * @param parameters + * @return + */ + protected static final T findParameter(String key, boolean forceString, ParameterProvider... parameters) { + return (T) Arrays.stream(parameters).map(p -> p.getParameter(key)).filter(Objects::nonNull).map(p -> { + if (forceString) { + return String.valueOf(p); + } + if ("true".equalsIgnoreCase(p)) { + return Boolean.TRUE; + } + if ("false".equalsIgnoreCase(p)) { + return Boolean.FALSE; + } + try { + return Double.valueOf(p); + } catch (Throwable e) { + } + return p; + }).findAny().orElse(null); + } + + + /** + * Adapt the request of Mesh REST model to an OpenAPI model. + * + * @param + * @param + * @param r + * @return + */ + protected static O adaptRequest(R r) { + return adaptRequest(r, Optional.empty()); + } + + /** + * Adapt the request of a selected Mesh REST model to an OpenAPI model. + * + * @param + * @param + * @param r + * @param maybeEndClass optional custom end model + * @return + */ + protected static O adaptRequest(R r, Optional> maybeEndClass) { + if (r == null) { + return null; + } + try { + String modelName = maybeEndClass.map(Class::getSimpleName).orElse(r.getClass().getSimpleName()); + Class openApiModelClass = (Class) Class.forName("org.openapitools.client.model." + modelName); + return JSON.getGson().fromJson(r.toJson(), openApiModelClass); + } catch (JsonSyntaxException | ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } + } + + public OpenAPIMeshRestClient(MeshRestClientConfig config, OkHttpClient okHttp) { + this.apiClient = new UpgradedApiClient(okHttp); + this.apiClient.setBasePath("%s://%s:%d".formatted((config.isSsl() ? "https" : "http"), config.getHost(), config.getPort())); + this.api = new UpgradedDefaultApi(this.apiClient); + this.config = config; + } + + @Override + public MeshRequest findNodeByUuid(String projectName, String uuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidGetWithHttpInfo( + uuid, projectName, + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters), + findParameter(RolePermissionParameters.ROLE_PERMISSION_QUERY_PARAM_KEY, parameters), + findParameter(NodeParameters.LANGUAGES_QUERY_PARAM_KEY, parameters), + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), + findParameter(NodeParameters.RESOLVE_LINKS_QUERY_PARAM_KEY, parameters)), NodeResponse.class); + } + + @Override + public MeshRequest createNode(String projectName, NodeCreateRequest nodeCreateRequest, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesPostWithHttpInfo(projectName, + adaptRequest(nodeCreateRequest)), NodeResponse.class); + } + + @Override + public MeshRequest createNode(String uuid, String projectName, NodeCreateRequest nodeCreateRequest, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidPostWithHttpInfo(uuid, projectName, adaptRequest(nodeCreateRequest)), + NodeResponse.class); + } + + @Override + public MeshRequest upsertNode(String projectName, String uuid, NodeUpsertRequest nodeUpsertRequest, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidPostWithHttpInfo(uuid, projectName, adaptRequest(nodeUpsertRequest, Optional.of(org.openapitools.client.model.NodeUpdateRequest.class))), + NodeResponse.class); + } + + @Override + public MeshRequest updateNode(String projectName, String uuid, NodeUpdateRequest nodeUpdateRequest, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidPostWithHttpInfo(uuid, projectName, + adaptRequest(nodeUpdateRequest)), NodeResponse.class); + } + + @Override + public MeshRequest deleteNode(String projectName, String uuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidDeleteWithHttpInfo(uuid, projectName, + findParameter(BranchParameters.BRANCH_QUERY_PARAM_KEY, parameters), + findParameter(DeleteParameters.RECURSIVE_PARAMETER_KEY, parameters)), EmptyResponse.class); + } + + @Override + public MeshRequest deleteNode(String projectName, String uuid, String languageTag, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidLanguagesLanguageDeleteWithHttpInfo( + languageTag, uuid, projectName, + findParameter(BranchParameters.BRANCH_QUERY_PARAM_KEY, parameters), + findParameter(DeleteParameters.RECURSIVE_PARAMETER_KEY, parameters)), EmptyResponse.class); + } + + @Override + public MeshRequest findNodes(String projectName, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesGetWithHttpInfo(projectName, + findParameter(RolePermissionParameters.ROLE_PERMISSION_QUERY_PARAM_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(NodeParameters.RESOLVE_LINKS_QUERY_PARAM_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters), + findParameter(PagingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(NodeParameters.LANGUAGES_QUERY_PARAM_KEY, parameters), + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), + findParameter(PagingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), NodeListResponse.class); + } + + @Override + public MeshRequest findNodeChildren(String projectName, String parentNodeUuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidChildrenGetWithHttpInfo( + parentNodeUuid, projectName, + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(NodeParameters.RESOLVE_LINKS_QUERY_PARAM_KEY, parameters), + findParameter(PagingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(NodeParameters.LANGUAGES_QUERY_PARAM_KEY, parameters), + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), + findParameter(PagingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), NodeListResponse.class); + } + + @Override + public MeshRequest findNodesForTag(String projectName, String tagFamilyUuid, String tagUuid, + ParameterProvider... parameters) { + + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidTagsTagUuidGetWithHttpInfo( + tagFamilyUuid, tagUuid, projectName, + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters)), NodeListResponse.class); + } + + @Override + public MeshRequest addTagToNode(String projectName, String nodeUuid, String tagUuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidTagsTagUuidPostWithHttpInfo( + tagUuid, nodeUuid, projectName, + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters)), NodeResponse.class); + } + + @Override + public MeshRequest removeTagFromNode(String projectName, String nodeUuid, String tagUuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidTagsTagUuidDeleteWithHttpInfo(tagUuid, nodeUuid, projectName), EmptyResponse.class); + } + + @Override + public MeshRequest moveNode(String projectName, String nodeUuid, String targetFolderUuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidMoveToToUuidPostWithHttpInfo( + targetFolderUuid, nodeUuid, projectName, + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters)), EmptyResponse.class); + } + + @Override + public MeshRequest findTagsForNode(String projectName, String nodeUuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidTagsGetWithHttpInfo(nodeUuid, projectName, + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters)), TagListResponse.class); + } + + @Override + public MeshRequest updateTagsForNode(String projectName, String nodeUuid, + TagListUpdateRequest request, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidTagsPostWithHttpInfo( + nodeUuid, projectName, + adaptRequest(request)), TagListResponse.class); + } + + @Override + public MeshRequest getNodePublishStatus(String projectName, String nodeUuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidPublishedGetWithHttpInfo(nodeUuid, projectName), PublishStatusResponse.class); + } + + @Override + public MeshRequest getNodeLanguagePublishStatus(String projectName, String nodeUuid, + String languageTag, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidLanguagesLanguagePublishedGetWithHttpInfo(languageTag, nodeUuid, projectName), + PublishStatusModel.class); + } + + @Override + public MeshRequest publishNode(String projectName, String nodeUuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidPublishedPostWithHttpInfo(nodeUuid, projectName, + findParameter(PublishParameters.RECURSIVE_PARAMETER_KEY, parameters)), PublishStatusResponse.class); + } + + @Override + public MeshRequest publishNodeLanguage(String projectName, String nodeUuid, String languageTag, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidLanguagesLanguagePublishedPostWithHttpInfo(languageTag, nodeUuid, projectName), + PublishStatusModel.class); + } + + @Override + public MeshRequest takeNodeOffline(String projectName, String nodeUuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidPublishedDeleteWithHttpInfo(nodeUuid, projectName, + findParameter(PublishParameters.RECURSIVE_PARAMETER_KEY, parameters)), EmptyResponse.class); + } + + @Override + public MeshRequest takeNodeLanguageOffline(String projectName, String nodeUuid, String languageTag, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidLanguagesLanguagePublishedDeleteWithHttpInfo(languageTag, nodeUuid, projectName), + EmptyResponse.class); + } + + @Override + public MeshRequest listNodeVersions(String projectName, String nodeUuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidVersionsGetWithHttpInfo(nodeUuid, projectName, + findParameter(NodeParameters.LANGUAGES_QUERY_PARAM_KEY, parameters), + findParameter(NodeParameters.RESOLVE_LINKS_QUERY_PARAM_KEY, parameters)), + NodeVersionsResponse.class); + } + + @Override + public MeshRequest getNodeRolePermissions(String projectName, String uuid) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidRolePermissionsGetWithHttpInfo(uuid, projectName), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest grantNodeRolePermissions(String projectName, String uuid, + ObjectPermissionGrantRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectNodesNodeUuidRolePermissionsPostWithHttpInfo(uuid, projectName, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest revokeNodeRolePermissions(String projectName, String uuid, + ObjectPermissionRevokeRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectNodesNodeUuidRolePermissionsPutWithHttpInfo(uuid, projectName, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest createTag(String projectName, String tagFamilyUuid, TagCreateRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidTagsPostWithHttpInfo(tagFamilyUuid, projectName, adaptRequest(request)), TagResponse.class); + } + + @Override + public MeshRequest findTagByUuid(String projectName, String tagFamilyUuid, String uuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidTagsTagUuidGetWithHttpInfo(tagFamilyUuid, uuid, projectName, + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters)), TagResponse.class); + } + + @Override + public MeshRequest updateTag(String projectName, String tagFamilyUuid, String uuid, + TagUpdateRequest request, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidTagsTagUuidPostWithHttpInfo(tagFamilyUuid, uuid, projectName, + adaptRequest(request)), TagResponse.class); + } + + @Override + public MeshRequest createTag(String projectName, String tagFamilyUuid, String uuid, + TagCreateRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidTagsPostWithHttpInfo(tagFamilyUuid, projectName, adaptRequest(request)), TagResponse.class); + } + + @Override + public MeshRequest deleteTag(String projectName, String tagFamilyUuid, String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidTagsTagUuidDeleteWithHttpInfo(tagFamilyUuid, uuid, projectName), EmptyResponse.class); + } + + @Override + public MeshRequest findTags(String projectName, String tagFamilyUuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidTagsGetWithHttpInfo(tagFamilyUuid, projectName, + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), TagListResponse.class); + } + + @Override + public MeshRequest getTagRolePermissions(String projectName, String tagFamilyUuid, + String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidTagsTagUuidRolePermissionsGetWithHttpInfo(tagFamilyUuid, uuid, projectName), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest grantTagRolePermissions(String projectName, String tagFamilyUuid, + String uuid, ObjectPermissionGrantRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidTagsTagUuidRolePermissionsPostWithHttpInfo(tagFamilyUuid, uuid, projectName, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest revokeTagRolePermissions(String projectName, String tagFamilyUuid, + String uuid, ObjectPermissionRevokeRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidTagsTagUuidRolePermissionsPutWithHttpInfo(tagFamilyUuid, uuid, projectName, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest findProjectByUuid(String uuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectsProjectUuidGetWithHttpInfo(uuid, findParameter(RolePermissionParameters.ROLE_PERMISSION_QUERY_PARAM_KEY, parameters)), ProjectResponse.class); + } + + @Override + public MeshRequest findProjectByName(String name, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectGetWithHttpInfo(name), ProjectResponse.class); + } + + @Override + public MeshRequest findProjects(ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectsGetWithHttpInfo( + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(RolePermissionParameters.ROLE_PERMISSION_QUERY_PARAM_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), ProjectListResponse.class); + } + + @Override + public MeshRequest assignLanguageToProject(String projectUuid, String languageUuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectLanguagesLanguageUuidPostWithHttpInfo(languageUuid, projectUuid, findParameter(ProjectLoadParameters.LANGS_QUERY_PARAM_KEY, parameters)), ProjectResponse.class); + } + + @Override + public MeshRequest unassignLanguageFromProject(String projectUuid, String languageUuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectLanguagesLanguageUuidDeleteWithHttpInfo(languageUuid, projectUuid, findParameter(ProjectLoadParameters.LANGS_QUERY_PARAM_KEY, parameters)), ProjectResponse.class); + } + + @Override + public MeshRequest createProject(ProjectCreateRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectsPostWithHttpInfo(adaptRequest(request)), ProjectResponse.class); + } + + @Override + public MeshRequest createProject(String uuid, ProjectCreateRequest request) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectsProjectUuidPostWithHttpInfo(uuid, adaptRequest(request, Optional.of(org.openapitools.client.model.ProjectUpdateRequest.class))), ProjectResponse.class); + } + + @Override + public MeshRequest updateProject(String uuid, ProjectUpdateRequest request, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectsProjectUuidPostWithHttpInfo(uuid, adaptRequest(request)), ProjectResponse.class); + } + + @Override + public MeshRequest deleteProject(String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectsProjectUuidDeleteWithHttpInfo(uuid), EmptyResponse.class); + } + + @Override + public MeshRequest purgeProject(String uuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectsProjectUuidDeleteWithHttpInfo(uuid), GenericMessageResponse.class); + } + + @Override + public MeshRequest getProjectRolePermissions(String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectsProjectUuidRolePermissionsGetWithHttpInfo(uuid), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest grantProjectRolePermissions(String uuid, + ObjectPermissionGrantRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectsProjectUuidRolePermissionsPostWithHttpInfo(uuid, adaptRequest(request)), ObjectPermissionGrantRequest.class); + } + + @Override + public MeshRequest revokeProjectRolePermissions(String uuid, + ObjectPermissionRevokeRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectsProjectUuidRolePermissionsPutWithHttpInfo(uuid, adaptRequest(request)), ObjectPermissionGrantRequest.class); + } + + @Override + public MeshRequest findTagFamilyByUuid(String projectName, String uuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidGetWithHttpInfo(uuid, projectName, findParameter(EtagParameters.ETAG_PARAM_KEY, parameters)), TagFamilyResponse.class); + } + + @Override + public MeshRequest findTagFamilies(String projectName, PagingParameters parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesGetWithHttpInfo(projectName, + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), TagFamilyListResponse.class); + } + + @Override + public MeshRequest createTagFamily(String projectName, TagFamilyCreateRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesPostWithHttpInfo(projectName, adaptRequest(request)), TagFamilyResponse.class); + } + + @Override + public MeshRequest deleteTagFamily(String projectName, String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidDeleteWithHttpInfo(uuid, projectName), EmptyResponse.class); + } + + @Override + public MeshRequest updateTagFamily(String projectName, String tagFamilyUuid, + TagFamilyUpdateRequest request, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidPost(tagFamilyUuid, projectName, + adaptRequest(request)), TagFamilyResponse.class); + } + + @Override + public MeshRequest createTagFamily(String projectName, String tagFamilyUuid, + TagFamilyCreateRequest request) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidPost(tagFamilyUuid, projectName, adaptRequest(request, Optional.of(org.openapitools.client.model.TagFamilyUpdateRequest.class))), TagFamilyResponse.class); + } + + @Override + public MeshRequest findTagFamilies(String projectName, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesGetWithHttpInfo(projectName, + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), TagFamilyListResponse.class); + } + + @Override + public MeshRequest getTagFamilyRolePermissions(String projectName, String tagFamilyUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidRolePermissionsGetWithHttpInfo(tagFamilyUuid, projectName), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest grantTagFamilyRolePermissions(String projectName, String tagFamilyUuid, + ObjectPermissionGrantRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidRolePermissionsPostWithHttpInfo(tagFamilyUuid, projectName, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest revokeTagFamilyRolePermissions(String projectName, + String tagFamilyUuid, ObjectPermissionRevokeRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectTagFamiliesTagFamilyUuidRolePermissionsPutWithHttpInfo(tagFamilyUuid, projectName, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest webroot(String projectName, String path, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), (UpgradedCall) api.apiV2ProjectWebrootPathGetCall(path, projectName, + findParameter(ImageManipulationParameters.FOCAL_POINT_Z_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.RECT_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.WIDTH_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.HEIGHT_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.RESIZE_MODE_QUERY_PARAM_KEY, parameters), + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), + findParameter(ImageManipulationParameters.FOCAL_POINT_Y_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.CROP_MODE_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.FOCAL_POINT_X_QUERY_PARAM_KEY, parameters), null), MeshWebrootResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest webroot(String projectName, String[] pathSegments, + ParameterProvider... parameters) { + return webroot(projectName, Arrays.stream(pathSegments).collect(Collectors.joining("/")), parameters); + } + + @Override + public MeshRequest webrootUpdate(String projectName, String path, NodeUpdateRequest nodeUpdateRequest, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectWebrootPathPostWithHttpInfo(path, projectName, adaptRequest(nodeUpdateRequest)), NodeResponse.class); + } + + @Override + public MeshRequest webrootUpdate(String projectName, String[] pathSegments, + NodeUpdateRequest nodeUpdateRequest, ParameterProvider... parameters) { + return webrootUpdate(projectName, Arrays.stream(pathSegments).collect(Collectors.joining("/")), nodeUpdateRequest, parameters); + } + + @Override + public MeshRequest webrootCreate(String projectName, String path, NodeCreateRequest nodeCreateRequest, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectWebrootPathPostWithHttpInfo(path, projectName, adaptRequest(nodeCreateRequest, Optional.of(org.openapitools.client.model.NodeUpdateRequest.class))), NodeResponse.class); + } + + @Override + public MeshRequest webrootCreate(String projectName, String[] pathSegments, + NodeCreateRequest nodeCreateRequest, ParameterProvider... parameters) { + return webrootCreate(projectName, Arrays.stream(pathSegments).collect(Collectors.joining("/")), nodeCreateRequest, parameters); + } + + @Override + public MeshRequest createSchema(SchemaCreateRequest request, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2SchemasPostWithHttpInfo(adaptRequest(request)), SchemaResponse.class); + } + + @Override + public MeshRequest createSchema(String uuid, SchemaCreateRequest request, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2SchemasSchemaUuidPostWithHttpInfo(uuid, + findParameter(SchemaUpdateParameters.UPDATE_ASSIGNED_BRANCHES_QUERY_PARAM_KEY, parameters), + findParameter(SchemaUpdateParameters.UPDATE_BRANCH_NAMES_QUERY_PARAM_KEY, parameters), + findParameter(SchemaUpdateParameters.STRICT_VALIDATION_KEY, parameters), + adaptRequest(request, Optional.of(org.openapitools.client.model.SchemaUpdateRequest.class))), SchemaResponse.class); + } + + @Override + public MeshRequest findSchemaByUuid(String uuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2SchemasSchemaUuidGetWithHttpInfo(uuid, + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters)), SchemaResponse.class); + } + + @Override + public MeshRequest updateSchema(String uuid, SchemaUpdateRequest request, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2SchemasSchemaUuidPostWithHttpInfo(uuid, + findParameter(SchemaUpdateParameters.UPDATE_ASSIGNED_BRANCHES_QUERY_PARAM_KEY, parameters), + findParameter(SchemaUpdateParameters.UPDATE_BRANCH_NAMES_QUERY_PARAM_KEY, parameters), + findParameter(SchemaUpdateParameters.STRICT_VALIDATION_KEY, parameters), + adaptRequest(request)), GenericMessageResponse.class); + } + + @Override + public MeshRequest diffSchema(String uuid, SchemaModel request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2SchemasSchemaUuidDiffPostWithHttpInfo(uuid, adaptRequest(request)), SchemaChangesListModel.class); + } + + @Override + public MeshRequest deleteSchema(String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2SchemasSchemaUuidDeleteWithHttpInfo(uuid), EmptyResponse.class); + } + + @Override + public MeshRequest findSchemas(ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2SchemasGetWithHttpInfo( + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), SchemaListResponse.class); + } + + @Override + public MeshRequest findMicroschemas(ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2MicroschemasGetWithHttpInfo( + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), MicroschemaListResponse.class); + } + + @Override + public MeshRequest applyChangesToSchema(String uuid, SchemaChangesListModel changes) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2SchemasSchemaUuidChangesPostWithHttpInfo(uuid, adaptRequest(changes)), GenericMessageResponse.class); + } + + @Override + public MeshRequest assignSchemaToProject(String projectName, String schemaUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectSchemasSchemaUuidPostWithHttpInfo(schemaUuid, projectName), SchemaResponse.class); + } + + @Override + public MeshRequest unassignSchemaFromProject(String projectName, String schemaUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectSchemasSchemaUuidDeleteWithHttpInfo(schemaUuid, projectName), EmptyResponse.class); + } + + @Override + public MeshRequest findSchemas(String projectName, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectSchemasGetWithHttpInfo(projectName, + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), SchemaListResponse.class); + } + + @Override + public MeshRequest assignMicroschemaToProject(String projectName, String microschemaUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectMicroschemasMicroschemaUuidPostWithHttpInfo(microschemaUuid, projectName), MicroschemaResponse.class); + } + + @Override + public MeshRequest unassignMicroschemaFromProject(String projectName, String microschemaUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectMicroschemasMicroschemaUuidDeleteWithHttpInfo(microschemaUuid, projectName), EmptyResponse.class); + } + + @Override + public MeshRequest findMicroschemas(String projectName, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectMicroschemasGetWithHttpInfo(projectName, + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), MicroschemaListResponse.class); + } + + @Override + public MeshRequest getSchemaRolePermissions(String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2SchemasSchemaUuidRolePermissionsGetWithHttpInfo(uuid), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest grantSchemaRolePermissions(String uuid, + ObjectPermissionGrantRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2SchemasSchemaUuidRolePermissionsPostWithHttpInfo(uuid, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest revokeSchemaRolePermissions(String uuid, + ObjectPermissionRevokeRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2SchemasSchemaUuidRolePermissionsPutWithHttpInfo(uuid, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest findGroupByUuid(String uuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2GroupsGroupUuidGetWithHttpInfo(uuid, + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters)), GroupResponse.class); + } + + @Override + public MeshRequest findGroups(ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2GroupsGetWithHttpInfo( + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(RolePermissionParameters.ROLE_PERMISSION_QUERY_PARAM_KEY, parameters), + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), GroupListResponse.class); + } + + @Override + public MeshRequest createGroup(GroupCreateRequest createRequest) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2GroupsPostWithHttpInfo(adaptRequest(createRequest)), GroupResponse.class); + } + + @Override + public MeshRequest createGroup(String uuid, GroupCreateRequest createRequest) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2GroupsGroupUuidPostWithHttpInfo(uuid, adaptRequest(createRequest, Optional.of(org.openapitools.client.model.GroupUpdateRequest.class))), GroupResponse.class); + } + + @Override + public MeshRequest updateGroup(String uuid, GroupUpdateRequest request, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2GroupsGroupUuidPostWithHttpInfo(uuid, + adaptRequest(request)), GroupResponse.class); + } + + @Override + public MeshRequest deleteGroup(String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2GroupsGroupUuidDeleteWithHttpInfo(uuid), EmptyResponse.class); + } + + @Override + public MeshRequest addUserToGroup(String groupUuid, String userUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2GroupsGroupUuidUsersUserUuidPostWithHttpInfo(groupUuid, userUuid), GroupResponse.class); + } + + @Override + public MeshRequest removeUserFromGroup(String groupUuid, String userUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2GroupsGroupUuidUsersUserUuidDeleteWithHttpInfo(groupUuid, userUuid), EmptyResponse.class); + } + + @Override + public MeshRequest addRoleToGroup(String groupUuid, String roleUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2GroupsGroupUuidRolesRoleUuidPostWithHttpInfo(groupUuid, roleUuid), GroupResponse.class); + } + + @Override + public MeshRequest removeRoleFromGroup(String groupUuid, String roleUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2GroupsGroupUuidRolesRoleUuidDeleteWithHttpInfo(groupUuid, roleUuid), EmptyResponse.class); + } + + @Override + public MeshRequest getGroupRolePermissions(String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2GroupsGroupUuidRolePermissionsGetWithHttpInfo(uuid), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest grantGroupRolePermissions(String uuid, + ObjectPermissionGrantRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2GroupsGroupUuidRolePermissionsPostWithHttpInfo(uuid, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest revokeGroupRolePermissions(String uuid, + ObjectPermissionRevokeRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2GroupsGroupUuidRolePermissionsPutWithHttpInfo(uuid, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest findUserByUuid(String uuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2UsersUserUuidGetWithHttpInfo(uuid, + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters), + findParameter(RolePermissionParameters.ROLE_PERMISSION_QUERY_PARAM_KEY, parameters), + findParameter(NodeParameters.LANGUAGES_QUERY_PARAM_KEY, parameters), + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(NodeParameters.RESOLVE_LINKS_QUERY_PARAM_KEY, parameters), + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters)), UserResponse.class); + } + + @Override + public MeshRequest findUsers(ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2UsersGetWithHttpInfo( + findParameter(RolePermissionParameters.ROLE_PERMISSION_QUERY_PARAM_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(NodeParameters.RESOLVE_LINKS_QUERY_PARAM_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters), + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(NodeParameters.LANGUAGES_QUERY_PARAM_KEY, parameters), + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), UserListResponse.class); + } + + @Override + public MeshRequest createUser(UserCreateRequest request, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2UsersPostWithHttpInfo(adaptRequest(request)), UserResponse.class); + } + + @Override + public MeshRequest createUser(String uuid, UserCreateRequest request, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2UsersUserUuidPostWithHttpInfo(uuid, + getAPIKey(), adaptRequest(request, Optional.of(org.openapitools.client.model.UserUpdateRequest.class))), UserResponse.class); + } + + @Override + public MeshRequest updateUser(String uuid, UserUpdateRequest request, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2UsersUserUuidPostWithHttpInfo(uuid, getAPIKey(), adaptRequest(request)), UserResponse.class); + } + + @Override + public MeshRequest deleteUser(String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2UsersUserUuidDeleteWithHttpInfo(uuid), EmptyResponse.class); + } + + @Override + public MeshRequest findUsersOfGroup(String groupUuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2GroupsGroupUuidUsersGetWithHttpInfo(groupUuid, + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), UserListResponse.class); + } + + @Override + public MeshRequest readUserPermissions(String uuid, String pathToElement) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2UsersUserUuidPermissionsPathGetWithHttpInfo(pathToElement, uuid), UserPermissionResponse.class); + } + + @Override + public MeshRequest getUserResetToken(String userUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2UsersUserUuidResetTokenPostWithHttpInfo(userUuid), UserResetTokenResponse.class); + } + + @Override + public MeshRequest issueAPIToken(String userUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2UsersUserUuidTokenPostWithHttpInfo(userUuid), UserAPITokenResponse.class); + } + + @Override + public MeshRequest invalidateAPIToken(String userUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2UsersUserUuidTokenDeleteWithHttpInfo(userUuid), GenericMessageResponse.class); + } + + @Override + public MeshRequest getUserRolePermissions(String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2UsersUserUuidRolePermissionsGetWithHttpInfo(uuid), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest grantUserRolePermissions(String uuid, + ObjectPermissionGrantRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2UsersUserUuidRolePermissionsPostWithHttpInfo(uuid, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest revokeUserRolePermissions(String uuid, + ObjectPermissionRevokeRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2UsersUserUuidRolePermissionsPutWithHttpInfo(uuid, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest findRoleByUuid(String uuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2RolesRoleUuidGetWithHttpInfo(uuid, + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters)), RoleResponse.class); + } + + @Override + public MeshRequest findRoles(ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2RolesGetWithHttpInfo( + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), RoleListResponse.class); + } + + @Override + public MeshRequest createRole(RoleCreateRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2RolesPostWithHttpInfo(adaptRequest(request)), RoleResponse.class); + } + + @Override + public MeshRequest createRole(String uuid, RoleCreateRequest request) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2RolesRoleUuidPostWithHttpInfo(uuid, adaptRequest(request, Optional.of(org.openapitools.client.model.RoleUpdateRequest.class))), RoleResponse.class); + } + + @Override + public MeshRequest deleteRole(String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2RolesRoleUuidDeleteWithHttpInfo(uuid), EmptyResponse.class); + } + + @Override + public MeshRequest findRolesForGroup(String groupUuid, ParameterProvider... parameter) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2GroupsGroupUuidRolesGetWithHttpInfo(groupUuid, + groupUuid, null, null, groupUuid, groupUuid), RoleListResponse.class); + } + + @Override + public MeshRequest updateRolePermissions(String roleUuid, String pathToElement, + RolePermissionRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2RolesRoleUuidPermissionsPathPostWithHttpInfo(pathToElement, roleUuid, adaptRequest(request)), GenericMessageResponse.class); + } + + @Override + public MeshRequest readRolePermissions(String roleUuid, String pathToElement) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2RolesRoleUuidPermissionsPathGetWithHttpInfo(pathToElement, roleUuid), RolePermissionResponse.class); + } + + @Override + public MeshRequest updateRole(String uuid, RoleUpdateRequest restRole, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2RolesRoleUuidPostWithHttpInfo(uuid, + adaptRequest(restRole)), RoleResponse.class); + } + + @Override + public MeshRequest getRoleRolePermissions(String uuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2RolesRoleUuidGetWithHttpInfo(uuid, + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest grantRoleRolePermissions(String uuid, + ObjectPermissionGrantRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2RolesRoleUuidRolePermissionsPostWithHttpInfo(uuid, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest revokeRoleRolePermissions(String uuid, + ObjectPermissionRevokeRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2RolesRoleUuidRolePermissionsPutWithHttpInfo(uuid, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public Single login() { + return Single.fromCallable(() -> api.apiV2AuthLoginPost(new LoginRequest() + .username(authentication.getUsername()) + .password(authentication.getPassword()) + .newPassword(authentication.getNewPassword()))) + .map(tokenResponse -> { + authentication.setToken(tokenResponse.getToken()); + apiClient.setBearerToken(tokenResponse.getToken()); + return new GenericMessageResponse("OK"); + }); + } + + @Override + public Single logout() { + return Single.fromCallable(() -> api.apiV2AuthLogoutGet()) + .map(response -> { + authentication.setToken(null); + return new GenericMessageResponse("OK"); + }); + } + + @Override + public MeshRequest me(ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2AuthMeGetWithHttpInfo(), UserResponse.class); + } + + @Override + public MeshRequest searchNodes(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2SearchNodesPostCall(json, + findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(BranchParameters.BRANCH_QUERY_PARAM_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters), null), NodeListResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchNodesRaw(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2RawSearchNodesPostCall(json, + findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), null), ObjectNode.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchNodes(String projectName, String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2ProjectSearchNodesPostCall(json, projectName, + findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters), null), NodeListResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchNodesRaw(String projectName, String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl(apiClient.getHttpClient(), api.apiV2ProjectRawSearchNodesPostCall(json, projectName, findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), null), ObjectNode.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchUsers(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2SearchUsersPostCall(json, + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters), null), UserListResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchUsersRaw(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2RawSearchUsersPostCall(json, findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), null), ObjectNode.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchGroups(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2SearchGroupsPostCall(json, findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters), null), GroupListResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchGroupsRaw(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2RawSearchGroupsPostCall(json, findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), null), ObjectNode.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchRoles(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2SearchRolesPostCall(json, findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters), null), RoleListResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchRolesRaw(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2RawSearchRolesPostCall(json, findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), null), ObjectNode.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchProjects(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2SearchProjectsPostCall(json, findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters), null), ProjectListResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchProjectsRaw(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2RawSearchProjectsPostCall(json, findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), null), ObjectNode.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchTags(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2SearchTagsPostCall(json, findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters), null), TagListResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchTagsRaw(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2RawSearchTagsPostCall(json, findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), null), ObjectNode.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchTags(String projectName, String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2ProjectSearchTagsPostCall(json, projectName, findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters), null), TagListResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchTagsRaw(String projectName, String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl(apiClient.getHttpClient(), api.apiV2ProjectRawSearchTagsPostCall(json, projectName, findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), null), ObjectNode.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchTagFamilies(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl(apiClient.getHttpClient(), api.apiV2RawSearchTagFamiliesPostCall(json, findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), null), ObjectNode.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchTagFamiliesRaw(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl(apiClient.getHttpClient(), api.apiV2RawSearchTagFamiliesPostCall(json, findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), null), ObjectNode.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchTagFamilies(String projectName, String json, + ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2ProjectSearchTagFamiliesPostCall(json, projectName, findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters), null), TagFamilyListResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchTagFamiliesRaw(String projectName, String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl(apiClient.getHttpClient(), api.apiV2ProjectRawSearchTagFamiliesPostCall(json, projectName, findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), null), ObjectNode.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchSchemas(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2SearchSchemasPostCall(json, findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters), null), SchemaListResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchSchemasRaw(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2RawSearchSchemasPostCall(json, findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), null), ObjectNode.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchMicroschemas(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2SearchMicroschemasPostCall(json, findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters), null), MicroschemaListResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest searchMicroschemasRaw(String json, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2RawSearchMicroschemasPostCall(json, findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), null), ObjectNode.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest invokeIndexClear(ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2SearchClearPostWithHttpInfo( + findParameter(IndexMaintenanceParameters.INDEX_PARAMETER_KEY, parameters)), GenericMessageResponse.class); + } + + @Override + public MeshRequest invokeIndexSync(ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2SearchSyncPostWithHttpInfo( + findParameter(IndexMaintenanceParameters.INDEX_PARAMETER_KEY, parameters)), GenericMessageResponse.class); + } + + @Override + public MeshRequest searchStatus() { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2SearchStatusGetWithHttpInfo(), SearchStatusResponse.class); + } + + @Override + public MeshRequest meshStatus() { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2AdminStatusGetWithHttpInfo(), MeshStatusResponse.class); + } + + @Override + public MeshRequest clusterStatus() { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2AdminClusterStatusGetWithHttpInfo(), ClusterStatusResponse.class); + } + + @Override + public MeshRequest checkConsistency(ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2AdminConsistencyCheckGetWithHttpInfo( + findParameter(ConsistencyCheckParameters.ASYNC_PARAMETER_KEY, parameters)), ConsistencyCheckResponse.class); + } + + @Override + public MeshRequest repairConsistency(ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2AdminConsistencyRepairPostWithHttpInfo( + findParameter(ConsistencyCheckParameters.ASYNC_PARAMETER_KEY, parameters)), ConsistencyCheckResponse.class); + } + + @Override + public MeshRequest debugInfo(String... include) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2AdminDebuginfoGetWithHttpInfo(Arrays.stream(include).collect(Collectors.joining(","))), MeshBinaryResponse.class); + } + + @Override + public MeshRequest loadCoordinationMaster() { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2AdminCoordinatorMasterGetWithHttpInfo(), CoordinatorMasterResponse.class); + } + + @Override + public MeshRequest setCoordinationMaster() { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2AdminCoordinatorMasterPostWithHttpInfo(), GenericMessageResponse.class); + } + + @Override + public MeshRequest clearCache() { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2AdminCacheDeleteWithHttpInfo(), GenericMessageResponse.class); + } + + @Override + public MeshRequest deployPlugin(PluginDeploymentRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2AdminPluginsPostWithHttpInfo(adaptRequest(request)), PluginResponse.class); + } + + @Override + public MeshRequest findPlugins(ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2AdminPluginsGetWithHttpInfo( + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), PluginListResponse.class); + } + + @Override + public MeshRequest findPlugin(String id) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2AdminPluginsIdGetWithHttpInfo(id), PluginResponse.class); + } + + @Override + public MeshRequest undeployPlugin(String id) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2AdminPluginsIdDeleteWithHttpInfo(id), GenericMessageResponse.class); + } + + @Override + public MeshRequest createMicroschema(MicroschemaCreateRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2MicroschemasPostWithHttpInfo(adaptRequest(request)), MicroschemaResponse.class); + } + + @Override + public MeshRequest createMicroschema(String uuid, MicroschemaCreateRequest request) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2MicroschemasMicroschemaUuidPostWithHttpInfo(uuid, adaptRequest(request)), MicroschemaResponse.class); + } + + @Override + public MeshRequest findMicroschemaByUuid(String uuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2MicroschemasMicroschemaUuidGetWithHttpInfo(uuid, + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters)), MicroschemaResponse.class); + } + + @Override + public MeshRequest updateMicroschema(String uuid, MicroschemaUpdateRequest request, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2MicroschemasMicroschemaUuidPostWithHttpInfo(uuid, adaptRequest(request)), GenericMessageResponse.class); + } + + @Override + public MeshRequest deleteMicroschema(String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2MicroschemasMicroschemaUuidDeleteWithHttpInfo(uuid), EmptyResponse.class); + } + + @Override + public MeshRequest applyChangesToMicroschema(String uuid, SchemaChangesListModel changes) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2MicroschemasMicroschemaUuidChangesPostWithHttpInfo(uuid, adaptRequest(changes)), GenericMessageResponse.class); + } + + @Override + public MeshRequest diffMicroschema(String uuid, MicroschemaModel request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2MicroschemasMicroschemaUuidDiffPostWithHttpInfo(uuid, adaptRequest(request)), SchemaChangesListModel.class); + } + + @Override + public MeshRequest getMicroschemaRolePermissions(String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2MicroschemasMicroschemaUuidRolePermissionsGetWithHttpInfo(uuid), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest grantMicroschemaRolePermissions(String uuid, + ObjectPermissionGrantRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2MicroschemasMicroschemaUuidRolePermissionsPostWithHttpInfo(uuid, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest revokeMicroschemaRolePermissions(String uuid, + ObjectPermissionRevokeRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2MicroschemasMicroschemaUuidRolePermissionsPutWithHttpInfo(uuid, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest updateNodeBinaryField(String projectName, String nodeUuid, String languageTag, + String nodeVersion, String fieldKey, InputStream fileData, long fileSize, String fileName, + String contentType, boolean publish, ParameterProvider... parameters) { + try { + File tmpFile = Files.createTempFile(fileName, fieldKey).toFile(); + FileUtils.copyInputStreamToFile(fileData, tmpFile); + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidBinaryFieldNamePostWithHttpInfo(fieldKey, nodeUuid, projectName, + findParameter("publish", parameters), tmpFile, languageTag, nodeVersion), NodeResponse.class); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest downloadBinaryField(String projectName, String nodeUuid, String languageTag, + String fieldKey, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl(apiClient.getHttpClient(), (UpgradedCall) api.apiV2ProjectNodesNodeUuidBinaryFieldNameGetCall(fieldKey, nodeUuid, projectName, + findParameter(ImageManipulationParameters.FOCAL_POINT_Z_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.RECT_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.WIDTH_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.HEIGHT_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.RESIZE_MODE_QUERY_PARAM_KEY, parameters), + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), + findParameter(ImageManipulationParameters.FOCAL_POINT_Y_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.CROP_MODE_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.FOCAL_POINT_X_QUERY_PARAM_KEY, parameters), null), MeshBinaryResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest downloadBinaryField(String projectName, String nodeUuid, String languageTag, + String fieldKey, long from, long to, ParameterProvider... parameters) { + MeshRequest request = downloadBinaryField(projectName, nodeUuid, languageTag, fieldKey, parameters); + request.setHeader("Range", String.format("bytes=%d-%d", from, to)); + return request; + } + + @Override + public MeshRequest transformNodeBinaryField(String projectName, String nodeUuid, String languageTag, + String version, String fieldKey, ImageManipulationParameters parameters) { + BinaryFieldTransformRequest transformRequest = new BinaryFieldTransformRequest(); + transformRequest.setCropRect(parameters.getRect()); + transformRequest.setWidth(parameters.getWidth()); + transformRequest.setHeight(parameters.getHeight()); + transformRequest.setCropMode(parameters.getCropMode()); + transformRequest.setResizeMode(parameters.getResizeMode()); + transformRequest.setLanguage(languageTag).setVersion(version); + if (parameters.hasFocalPoint()) { + transformRequest.setFocalPoint(parameters.getFocalPoint()); + } + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectNodesNodeUuidBinaryTransformFieldNamePostWithHttpInfo(fieldKey, nodeUuid, projectName, adaptRequest(transformRequest)), NodeResponse.class); + } + + @Override + public MeshRequest updateNodeBinaryFieldCheckStatus(String projectName, String nodeUuid, + String languageTag, String nodeVersion, String fieldKey, String secret, String branchUuid, + BinaryCheckStatus status, String reason) { + BinaryCheckUpdateRequest updateRequest = new BinaryCheckUpdateRequest() + .setStatus(status) + .setReason(reason); + + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidBinaryFieldNameCheckCallbackPostWithHttpInfo(languageTag, secret, fieldKey, nodeUuid, projectName, nodeVersion, adaptRequest(updateRequest)), NodeResponse.class); + } + + @Override + public MeshRequest upsertNodeBinaryFieldImageVariants(String projectName, String nodeUuid, + String fieldKey, ImageManipulationRequest request, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectNodesNodeUuidBinaryFieldNameVariantsPostWithHttpInfo(fieldKey, nodeUuid, projectName, + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), + findParameter(ImageManipulationRetrievalParameters.ORIGINAL_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationRetrievalParameters.FILESIZE_QUERY_PARAM_KEY, parameters), + adaptRequest(request)), ImageVariantsResponse.class); + } + + @Override + public MeshRequest clearNodeBinaryFieldImageVariants(String projectName, String nodeUuid, + String fieldKey, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectNodesNodeUuidBinaryFieldNameVariantsDeleteWithHttpInfo(fieldKey, nodeUuid, projectName, + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), + findParameter(ImageManipulationRetrievalParameters.ORIGINAL_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationRetrievalParameters.FILESIZE_QUERY_PARAM_KEY, parameters)), EmptyResponse.class); + } + + @Override + public MeshRequest getNodeBinaryFieldImageVariants(String projectName, String nodeUuid, + String fieldKey, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectNodesNodeUuidBinaryFieldNameVariantsGetWithHttpInfo(fieldKey, nodeUuid, projectName, + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), + findParameter(ImageManipulationRetrievalParameters.ORIGINAL_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationRetrievalParameters.FILESIZE_QUERY_PARAM_KEY, parameters)), ImageVariantsResponse.class); + } + + @Override + public MeshRequest updateNodeS3BinaryField(String projectName, String nodeUuid, String fieldKey, + S3BinaryUploadRequest request, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectNodesNodeUuidS3binaryFieldNamePostWithHttpInfo(fieldKey, nodeUuid, projectName, + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), adaptRequest(request)), S3RestResponse.class); + } + + @Override + public MeshRequest extractMetadataNodeS3BinaryField(String projectName, String nodeUuid, + String fieldKey, S3BinaryMetadataRequest request, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectNodesNodeUuidS3binaryFieldNameParseMetadataPostWithHttpInfo(fieldKey, nodeUuid, projectName, + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), adaptRequest(request)), NodeResponse.class); + } + + @Override + public MeshRequest resolveLinks(String body, ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl(apiClient.getHttpClient(), api.apiV2UtilitiesLinkResolverPostCall(body, + findParameter(NodeParameters.LANGUAGES_QUERY_PARAM_KEY, parameters), + findParameter(NodeParameters.RESOLVE_LINKS_QUERY_PARAM_KEY, parameters), null), String.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest validateSchema(SchemaModel schema) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2UtilitiesValidateSchemaPostWithHttpInfo(adaptRequest(schema)), SchemaValidationResponse.class); + } + + @Override + public MeshRequest validateMicroschema(MicroschemaModel microschemaModel) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2UtilitiesValidateMicroschemaPostWithHttpInfo(adaptRequest(microschemaModel)), SchemaValidationResponse.class); + } + + @Override + public MeshRequest loadNavigation(String projectName, String uuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectNodesNodeUuidNavigationGetWithHttpInfo(uuid, projectName, + findParameter(NavigationParameters.MAX_DEPTH_QUERY_PARAM_KEY, parameters), + findParameter(NavigationParameters.INCLUDE_ALL_QUERY_PARAM_KEY, parameters)), NavigationResponse.class); + } + + @Override + public MeshRequest navroot(String projectName, String path, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectNavrootPathGetWithHttpInfo(path, projectName, + findParameter(NavigationParameters.MAX_DEPTH_QUERY_PARAM_KEY, parameters), + findParameter(NavigationParameters.INCLUDE_ALL_QUERY_PARAM_KEY, parameters)), NavigationResponse.class); + } + + @Override + public MeshWebsocket eventbus() { + // OpenAPI supports no websocket + return null; + } + + @Override + public MeshRequest createBranch(String projectName, BranchCreateRequest branchCreateRequest, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesPostWithHttpInfo(projectName, adaptRequest(branchCreateRequest)), BranchResponse.class); + } + + @Override + public MeshRequest createBranch(String projectName, String uuid, + BranchCreateRequest branchCreateRequest, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectBranchesBranchUuidPostWithHttpInfo(uuid, projectName, adaptRequest(branchCreateRequest, Optional.of(org.openapitools.client.model.BranchUpdateRequest.class))), BranchResponse.class); + } + + @Override + public MeshRequest findBranchByUuid(String projectName, String branchUuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidGetWithHttpInfo(branchUuid, projectName, + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters)), BranchResponse.class); + } + + @Override + public MeshRequest findBranches(String projectName, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesGetWithHttpInfo(projectName, + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(GenericParameters.ETAG_PARAM_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(GenericParameters.FIELDS_PARAM_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), BranchListResponse.class); + } + + @Override + public MeshRequest updateBranch(String projectName, String branchUuid, + BranchUpdateRequest request, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidPostWithHttpInfo(branchUuid, projectName, + adaptRequest(request)), BranchResponse.class); + } + + @Override + public MeshRequest getBranchSchemaVersions(String projectName, String branchUuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidSchemasGetWithHttpInfo(branchUuid, projectName, + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), BranchInfoSchemaList.class); + } + + @Override + public MeshRequest assignBranchSchemaVersions(String projectName, String branchUuid, + BranchInfoSchemaList schemaVersionReferences) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidSchemasPostWithHttpInfo(branchUuid, projectName, adaptRequest(schemaVersionReferences)), BranchInfoSchemaList.class); + } + + @Override + public MeshRequest assignBranchSchemaVersions(String projectName, String branchUuid, + SchemaReference... schemaVersionReferences) { + BranchInfoSchemaList list = new BranchInfoSchemaList(); + list.add(schemaVersionReferences); + return assignBranchSchemaVersions(projectName, branchUuid, list); + } + + @Override + public MeshRequest getBranchMicroschemaVersions(String projectName, String branchUuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidMicroschemasGetWithHttpInfo(branchUuid, projectName, + findParameter(SortingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(SortingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), BranchInfoMicroschemaList.class); + } + + @Override + public MeshRequest assignBranchMicroschemaVersions(String projectName, String branchUuid, + BranchInfoMicroschemaList microschemaVersionReferences) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidMicroschemasPostWithHttpInfo(branchUuid, projectName, adaptRequest(microschemaVersionReferences)), BranchInfoMicroschemaList.class); + } + + @Override + public MeshRequest assignBranchMicroschemaVersions(String projectName, String branchUuid, + MicroschemaReference... microschemaVersionReferences) { + BranchInfoMicroschemaList list = new BranchInfoMicroschemaList(); + list.add(microschemaVersionReferences); + return assignBranchMicroschemaVersions(projectName, branchUuid, list); + } + + @Override + public MeshRequest migrateBranchSchemas(String projectName, String branchUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidMigrateSchemasPostWithHttpInfo(branchUuid, projectName), GenericMessageResponse.class); + } + + @Override + public MeshRequest migrateBranchMicroschemas(String projectName, String branchUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidMigrateMicroschemasPostWithHttpInfo(branchUuid, projectName), GenericMessageResponse.class); + } + + @Override + public MeshRequest setLatestBranch(String projectName, String branchUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidLatestPostWithHttpInfo(branchUuid, projectName), BranchResponse.class); + } + + @Override + public MeshRequest addTagToBranch(String projectName, String branchUuid, String tagUuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidTagsTagUuidPostWithHttpInfo(tagUuid, branchUuid, projectName), BranchResponse.class); + } + + @Override + public MeshRequest removeTagFromBranch(String projectName, String branchUuid, String tagUuid) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectBranchesBranchUuidTagsTagUuidDeleteWithHttpInfo(tagUuid, branchUuid, projectName), BranchResponse.class); + } + + @Override + public MeshRequest findTagsForBranch(String projectName, String branchUuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidTagsGetWithHttpInfo(branchUuid, projectName), TagListResponse.class); + } + + @Override + public MeshRequest updateTagsForBranch(String projectName, String branchUuid, + TagListUpdateRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidTagsPostWithHttpInfo(branchUuid, projectName, adaptRequest(request)), TagListResponse.class); + } + + @Override + public MeshRequest getBranchRolePermissions(String projectName, String uuid) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidRolePermissionsGetWithHttpInfo(uuid, projectName), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest grantBranchRolePermissions(String projectName, String uuid, + ObjectPermissionGrantRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidRolePermissionsPostWithHttpInfo(uuid, projectName, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest revokeBranchRolePermissions(String projectName, String uuid, + ObjectPermissionRevokeRequest request) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectBranchesBranchUuidRolePermissionsPutWithHttpInfo(uuid, projectName, adaptRequest(request)), ObjectPermissionResponse.class); + } + + @Override + public MeshRequest getApiInfo() { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2GetWithHttpInfo(), MeshServerInfoModel.class); + } + + @Override + public MeshRequest getRAML() { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), api.apiV2RamlGetCall(null), String.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest getOpenAPI() { + try { + return new OpenAPIMeshRawRequestImpl(apiClient.getHttpClient(), api.apiV2OpenapiYamlGetCall(null), String.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest graphql(String projectName, GraphQLRequest request, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectGraphqlPostWithHttpInfo(projectName, + findParameter(BranchParameters.BRANCH_QUERY_PARAM_KEY, parameters), + findParameter(SearchParameters.WAIT_PARAMETER_KEY, parameters), adaptRequest(request)), GraphQLResponse.class); + } + + @Override + public MeshRequest findJobs(ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2AdminJobsGetWithHttpInfo( + findParameter(JobParameters.FROM_VERSION_PARAMETER_KEY, parameters), + findParameter(JobParameters.MICROSCHEMA_NAME_PARAMETER_KEY, parameters), + findParameter(JobParameters.MICROSCHEMA_UUID_PARAMETER_KEY, parameters), + findParameter(JobParameters.BRANCH_NAME_PARAMETER_KEY, parameters), + findParameter(JobParameters.BRANCH_UUID_PARAMETER_KEY, parameters), + findParameter(JobParameters.TYPE_PARAMETER_KEY, parameters), + findParameter(JobParameters.SCHEMA_NAME_PARAMETER_KEY, parameters), + findParameter(JobParameters.STATUS_PARAMETER_KEY, parameters), + findParameter(JobParameters.SCHEMA_UUID_PARAMETER_KEY, parameters), + findParameter(JobParameters.TO_VERSION_PARAMETER_KEY, parameters)), JobListResponse.class); + } + + @Override + public MeshRequest findJobByUuid(String uuid) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2AdminJobsJobUuidGetWithHttpInfo(uuid), JobResponse.class); + } + + @Override + public MeshRequest deleteJob(String uuid) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2AdminJobsJobUuidDeleteWithHttpInfo(uuid), EmptyResponse.class); + } + + @Override + public MeshRequest resetJob(String uuid) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2AdminJobsJobUuidErrorDeleteWithHttpInfo(uuid), EmptyResponse.class); + } + + @Override + public MeshRequest processJob(String uuid) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2AdminJobsJobUuidProcessPostWithHttpInfo(uuid), JobResponse.class); + } + + @Override + public MeshRequest invokeJobProcessing() { + return new OpenAPIMeshRequestImpl(() -> api.apiV2AdminProcessJobsPostWithHttpInfo(), GenericMessageResponse.class); + } + + @Override + public MeshRequest get(String path) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), + new UpgradedCall(api.getApiClient().buildRequestBuilder(apiClient.getBasePath(), path, "GET", List.of(), List.of(), null, Map.of(), Map.of(), Map.of(), null, null), apiClient.getHttpClient()), + JsonObject.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest get(String path, Class responseClass) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), + new UpgradedCall(api.getApiClient().buildRequestBuilder(apiClient.getBasePath(), path, "GET", List.of(), List.of(), null, Map.of(), Map.of(), Map.of(), null, null), apiClient.getHttpClient()), + responseClass); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest post(String path) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), + new UpgradedCall(api.getApiClient().buildRequestBuilder(apiClient.getBasePath(), path, "POST", List.of(), List.of(), null, Map.of(), Map.of(), Map.of(), null, null), apiClient.getHttpClient()), + JsonObject.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest post(String path, JsonObject body) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), + new UpgradedCall(api.getApiClient().buildRequestBuilder(apiClient.getBasePath(), path, "POST", List.of(), List.of(), body, Map.of(), Map.of(), Map.of(), null, null), apiClient.getHttpClient()), + JsonObject.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest post(String path, Class responseClass) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), + new UpgradedCall(api.getApiClient().buildRequestBuilder(apiClient.getBasePath(), path, "POST", List.of(), List.of(), null, Map.of(), Map.of(), Map.of(), null, null), apiClient.getHttpClient()), + responseClass); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest post(String path, T request, Class responseClass) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), + new UpgradedCall(api.getApiClient().buildRequestBuilder(apiClient.getBasePath(), path, "POST", List.of(), List.of(), request, Map.of(), Map.of(), Map.of(), null, null), apiClient.getHttpClient()), + responseClass); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest put(String path) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), + new UpgradedCall(api.getApiClient().buildRequestBuilder(apiClient.getBasePath(), path, "PUT", List.of(), List.of(), null, Map.of(), Map.of(), Map.of(), null, null), apiClient.getHttpClient()), + JsonObject.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest put(String path, JsonObject body) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), + new UpgradedCall(api.getApiClient().buildRequestBuilder(apiClient.getBasePath(), path, "PUT", List.of(), List.of(), body, Map.of(), Map.of(), Map.of(), null, null), apiClient.getHttpClient()), + JsonObject.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest put(String path, Class responseClass) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), + new UpgradedCall(api.getApiClient().buildRequestBuilder(apiClient.getBasePath(), path, "PUT", List.of(), List.of(), null, Map.of(), Map.of(), Map.of(), null, null), apiClient.getHttpClient()), + responseClass); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest put(String path, T request, Class responseClass) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), + new UpgradedCall(api.getApiClient().buildRequestBuilder(apiClient.getBasePath(), path, "PUT", List.of(), List.of(), request, Map.of(), Map.of(), Map.of(), null, null), apiClient.getHttpClient()), + responseClass); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest delete(String path) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), + new UpgradedCall(api.getApiClient().buildRequestBuilder(apiClient.getBasePath(), path, "DELETE", List.of(), List.of(), null, Map.of(), Map.of(), Map.of(), null, null), apiClient.getHttpClient()), + JsonObject.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest deleteEmpty(String path) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), + new UpgradedCall(api.getApiClient().buildRequestBuilder(apiClient.getBasePath(), path, "DELETE", List.of(), List.of(), null, Map.of(), Map.of(), Map.of(), null, null), apiClient.getHttpClient()), + EmptyResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest delete(String path, Class responseClass) { + try { + return new OpenAPIMeshRawRequestImpl<>(apiClient.getHttpClient(), + new UpgradedCall(api.getApiClient().buildRequestBuilder(apiClient.getBasePath(), path, "DELETE", List.of(), List.of(), null, Map.of(), Map.of(), Map.of(), null, null), apiClient.getHttpClient()), + responseClass); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest ready() { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2HealthReadyGetWithHttpInfo(), EmptyResponse.class); + } + + @Override + public MeshRequest live() { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2HealthLiveGetWithHttpInfo(), EmptyResponse.class); + } + + @Override + public MeshRequest writable() { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2HealthWritableGetWithHttpInfo(), EmptyResponse.class); + } + + @Override + public MeshRequest loadLocalConfig() { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2AdminConfigGetWithHttpInfo(), LocalConfigModel.class); + } + + @Override + public MeshRequest updateLocalConfig(LocalConfigModel localConfigModel) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2AdminConfigPostWithHttpInfo(adaptRequest(localConfigModel)), LocalConfigModel.class); + } + + @Override + public MeshRequest webrootField(String projectName, String fieldName, String path, + ParameterProvider... parameters) { + try { + return new OpenAPIMeshRawRequestImpl(apiClient.getHttpClient(), api.apiV2ProjectWebrootfieldFieldNamePathGetCall(path, fieldName, projectName, + findParameter(ImageManipulationParameters.FOCAL_POINT_Z_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.RECT_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.WIDTH_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.HEIGHT_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.RESIZE_MODE_QUERY_PARAM_KEY, parameters), + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), + findParameter(ImageManipulationParameters.FOCAL_POINT_Y_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.CROP_MODE_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationParameters.FOCAL_POINT_X_QUERY_PARAM_KEY, parameters), null), MeshWebrootFieldResponse.class); + } catch (ApiException e) { + throw new IllegalStateException(e); + } + } + + @Override + public MeshRequest webrootField(String projectName, String fieldName, + String[] pathSegments, ParameterProvider... parameters) { + return webrootField(projectName, fieldName, Arrays.stream(pathSegments).collect(Collectors.joining("/")), parameters); + } + + @Override + public MeshRequest upsertWebrootFieldImageVariants(String projectName, String fieldName, + String path, ImageManipulationRequest request, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2ProjectWebrootfieldFieldNamePathPostWithHttpInfo(path, fieldName, projectName, + findParameter(VersioningParameters.VERSION_QUERY_PARAM_KEY, true, parameters), + findParameter(ImageManipulationRetrievalParameters.ORIGINAL_QUERY_PARAM_KEY, parameters), + findParameter(ImageManipulationRetrievalParameters.FILESIZE_QUERY_PARAM_KEY, parameters), + adaptRequest(request)), ImageVariantsResponse.class); + } + + @Override + public MeshRequest upsertWebrootFieldImageVariants(String projectName, String fieldName, + String[] pathSegments, ImageManipulationRequest request, ParameterProvider... parameters) { + return upsertWebrootFieldImageVariants(projectName, fieldName, Arrays.stream(pathSegments).collect(Collectors.joining("/")), request, parameters); + } + + @Override + public MeshRequest findLanguageByUuid(String uuid, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2LanguagesLanguageUuidGetWithHttpInfo(uuid), LanguageResponse.class); + } + + @Override + public MeshRequest findLanguageByTag(String tag, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2LanguagesTagLanguageTagGetWithHttpInfo(tag), LanguageResponse.class); + } + + @Override + public MeshRequest findLanguages(ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl<>(() -> api.apiV2LanguagesGetWithHttpInfo(findParameter(PagingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), LanguageListResponse.class); + } + + @Override + public MeshRequest findLanguageByUuid(String projectName, String uuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectLanguagesLanguageUuidGetWithHttpInfo(uuid, projectName), LanguageResponse.class); + } + + @Override + public MeshRequest findLanguageByTag(String projectName, String tag, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectLanguagesTagLanguageTagGetWithHttpInfo(tag, projectName), LanguageResponse.class); + } + + @Override + public MeshRequest findLanguages(String projectName, ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectLanguagesGet(projectName, + findParameter(PagingParameters.SORT_BY_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.PER_PAGE_PARAMETER_KEY, parameters), + findParameter(PagingParameters.SORT_ORDER_PARAMETER_KEY, parameters)), LanguageListResponse.class); + } + + @Override + public MeshRequest assignLanguageToProjectByUuid(String projectName, String uuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectLanguagesLanguageUuidPostWithHttpInfo(uuid, projectName, findParameter(ProjectLoadParameters.LANGS_QUERY_PARAM_KEY, parameters)), + ProjectResponse.class); + } + + @Override + public MeshRequest assignLanguageToProjectByTag(String projectName, String tag, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectLanguagesTagLanguageTagPostWithHttpInfo(tag, projectName, findParameter(ProjectLoadParameters.LANGS_QUERY_PARAM_KEY, parameters)), + ProjectResponse.class); + } + + @Override + public MeshRequest unassignLanguageFromProjectByUuid(String projectName, String uuid, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectLanguagesLanguageUuidDeleteWithHttpInfo(uuid, projectName, findParameter(ProjectLoadParameters.LANGS_QUERY_PARAM_KEY, parameters)), + ProjectResponse.class); + } + + @Override + public MeshRequest unassignLanguageFromProjectByTag(String projectName, String tag, + ParameterProvider... parameters) { + return new OpenAPIMeshRequestImpl(() -> api.apiV2ProjectLanguagesTagLanguageTagDeleteWithHttpInfo(tag, projectName, findParameter(ProjectLoadParameters.LANGS_QUERY_PARAM_KEY, parameters)), + ProjectResponse.class); + } + + @Override + public MeshRestClient setLogin(String username, String password) { + authentication.setLogin(username, password); + return this; + } + + @Override + public MeshRestClient setLogin(String username, String password, String newPassword) { + authentication.setLogin(username, password, newPassword); + return null; + } + + @Override + public void close() { + } + + @Override + public MeshRestClient setAPIKey(String apiKey) { + authentication.setToken(apiKey); + return this; + } + + @Override + public String getAPIKey() { + return authentication.getToken(); + } + + @Override + public MeshRestClient disableAnonymousAccess() { + apiClient.disableAnonymousAccess(true); + return this; + } + + @Override + public MeshRestClient enableAnonymousAccess() { + apiClient.disableAnonymousAccess(false); + return this; + } + + @Override + public MeshRestClient setAuthenticationProvider(JWTAuthentication authentication) { + this.authentication = authentication; + return this; + } + + @Override + public JWTAuthentication getAuthentication() { + return authentication; + } + + @Override + public MeshRestClientConfig getConfig() { + return config; + } +} diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/UpgradedApiClient.java b/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/UpgradedApiClient.java new file mode 100644 index 0000000000..654ffdfa8c --- /dev/null +++ b/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/UpgradedApiClient.java @@ -0,0 +1,118 @@ +package com.gentics.mesh.test.openapi; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.openapitools.client.ApiCallback; +import org.openapitools.client.ApiClient; +import org.openapitools.client.ApiException; +import org.openapitools.client.Pair; +import org.openapitools.client.ProgressRequestBody; + +import com.gentics.mesh.http.MeshHeaders; + +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.internal.http.HttpMethod; + +/** + * API client with an access to the request builder + */ +public class UpgradedApiClient extends ApiClient { + + private boolean disableAnonymousAccess; + + public UpgradedApiClient() { + super(); + } + + public UpgradedApiClient(OkHttpClient client) { + super(client); + } + + @SuppressWarnings("rawtypes") + public Request.Builder buildRequestBuilder(String baseUrl, String path, String method, List queryParams, + List collectionQueryParams, Object body, Map headerParams, + Map cookieParams, Map formParams, String[] authNames, ApiCallback callback) + throws ApiException { + final String url = buildUrl(baseUrl, path, queryParams, collectionQueryParams); + + // prepare HTTP request body + RequestBody reqBody; + String contentType = headerParams.get("Content-Type"); + String contentTypePure = contentType; + if (contentTypePure != null && contentTypePure.contains(";")) { + contentTypePure = contentType.substring(0, contentType.indexOf(";")); + } + if (!HttpMethod.permitsRequestBody(method)) { + reqBody = null; + } else if ("application/x-www-form-urlencoded".equals(contentTypePure)) { + reqBody = buildRequestBodyFormEncoding(formParams); + } else if ("multipart/form-data".equals(contentTypePure)) { + reqBody = buildRequestBodyMultipart(formParams); + } else if (body == null) { + if ("DELETE".equals(method)) { + // allow calling DELETE without sending a request body + reqBody = null; + } else { + // use an empty request body (for POST, PUT and PATCH) + reqBody = RequestBody.create("", contentType == null ? null : MediaType.parse(contentType)); + } + } else { + reqBody = serialize(body, contentType); + } + + List updatedQueryParams = new ArrayList<>(queryParams); + + // update parameters with authentication settings + updateParamsForAuth(authNames, updatedQueryParams, headerParams, cookieParams, requestBodyToString(reqBody), method, URI.create(url)); + + final Request.Builder reqBuilder = new Request.Builder().url(buildUrl(baseUrl, path, updatedQueryParams, collectionQueryParams)); + processHeaderParams(headerParams, reqBuilder); + processCookieParams(cookieParams, reqBuilder); + + // Associate callback with request (if not null) so interceptor can + // access it when creating ProgressResponseBody + reqBuilder.tag(callback); + + if (callback != null && reqBody != null) { + ProgressRequestBody progressRequestBody = new ProgressRequestBody(reqBody, callback); + reqBuilder.method(method, progressRequestBody); + } else { + reqBuilder.method(method, reqBody); + } + + if (disableAnonymousAccess) { + headerParams.put(MeshHeaders.ANONYMOUS_AUTHENTICATION, "disable"); + } + return reqBuilder; + } + + @SuppressWarnings("rawtypes") + @Override + public Request buildRequest(String baseUrl, String path, String method, List queryParams, + List collectionQueryParams, Object body, Map headerParams, + Map cookieParams, Map formParams, String[] authNames, ApiCallback callback) + throws ApiException { + return buildRequestBuilder(baseUrl, path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, authNames, callback).build(); + } + + @SuppressWarnings("rawtypes") + @Override + public UpgradedCall buildCall(String baseUrl, String path, String method, List queryParams, + List collectionQueryParams, Object body, Map headerParams, + Map cookieParams, Map formParams, String[] authNames, ApiCallback callback) + throws ApiException { + Request.Builder request = buildRequestBuilder(baseUrl, path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, authNames, callback); + + return new UpgradedCall(request, httpClient); + } + + public void disableAnonymousAccess(boolean b) { + this.disableAnonymousAccess = b; + } +} diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/UpgradedCall.java b/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/UpgradedCall.java new file mode 100644 index 0000000000..f6b23b67d3 --- /dev/null +++ b/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/UpgradedCall.java @@ -0,0 +1,103 @@ +package com.gentics.mesh.test.openapi; + +import java.io.IOException; + +import kotlin.jvm.functions.Function0; +import kotlin.reflect.KClass; +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Request.Builder; +import okhttp3.Response; +import okio.Timeout; + +/** + * Lazily build {@link Call} + */ +public class UpgradedCall implements Call { + + private final Request.Builder builder; + private final OkHttpClient client; + private Call call = null; + + public UpgradedCall(Builder builder, OkHttpClient client) { + this.builder = builder; + this.client = client; + } + + @Override + public void cancel() { + lazy().cancel(); + } + + @Override + public void enqueue(Callback arg0) { + lazy().enqueue(arg0); + } + + @Override + public Response execute() throws IOException { + return lazy().execute(); + } + + @Override + public boolean isCanceled() { + return lazy().isCanceled(); + } + + @Override + public boolean isExecuted() { + return lazy().isExecuted(); + } + + @Override + public Request request() { + return lazy().request(); + } + + @Override + public T tag(KClass arg0) { + return lazy().tag(arg0); + } + + @Override + public T tag(Class arg0) { + return lazy().tag(arg0); + } + + @Override + public T tag(KClass arg0, Function0 arg1) { + return lazy().tag(arg0, arg1); + } + + @Override + public T tag(Class arg0, Function0 arg1) { + return lazy().tag(arg0, arg1); + } + + @Override + public Timeout timeout() { + return lazy().timeout(); + } + + @Override + public UpgradedCall clone() { + return new UpgradedCall(builder, client); + } + + public Request.Builder getBuilder() { + return builder; + } + + public Request build() { + return lazy().request(); + } + + private Call lazy() { + if (call == null) { + call = client.newCall(builder.build()); + } + return call; + } +} diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/UpgradedDefaultApi.java b/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/UpgradedDefaultApi.java new file mode 100644 index 0000000000..d5a48818af --- /dev/null +++ b/tests/tests-core/src/main/java/com/gentics/mesh/test/openapi/UpgradedDefaultApi.java @@ -0,0 +1,1634 @@ +package com.gentics.mesh.test.openapi; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.openapitools.client.ApiCallback; +import org.openapitools.client.ApiException; +import org.openapitools.client.Pair; +import org.openapitools.client.api.DefaultApi; + +import com.google.gson.JsonParser; + +import io.vertx.core.json.JsonObject; + +/** + * An upgrade to the generated DefaultAPI, overriding its generation problems + */ +@SuppressWarnings("rawtypes") +public class UpgradedDefaultApi extends DefaultApi { + + private UpgradedApiClient localVarApiClient; + + public UpgradedDefaultApi(UpgradedApiClient apiClient) { + super(apiClient); + this.localVarApiClient = apiClient; + } + + @Override + public UpgradedApiClient getApiClient() { + return localVarApiClient; + } + + // Fix for no generated response + + public UpgradedCall apiV2RamlGetCall(final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = null; + + // create path and map variables + String localVarPath = "/api/v2/raml"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + final String[] localVarAccepts = { + "application/x-yaml" + }; + final String localVarAccept = getApiClient().selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + }; + final String localVarContentType = getApiClient().selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return getApiClient().buildCall(basePath, localVarPath, "GET", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2ProjectWebrootfieldFieldNamePathGetCall(@jakarta.annotation.Nonnull String path, @jakarta.annotation.Nonnull String fieldName, @jakarta.annotation.Nonnull String project, @jakarta.annotation.Nullable Double fpz, @jakarta.annotation.Nullable String rect, @jakarta.annotation.Nullable Double w, @jakarta.annotation.Nullable Double h, @jakarta.annotation.Nullable String resize, @jakarta.annotation.Nullable String version, @jakarta.annotation.Nullable Double fpy, @jakarta.annotation.Nullable String crop, @jakarta.annotation.Nullable Double fpx, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = null; + + // create path and map variables + String localVarPath = "/api/v2/{project}/webrootfield/{fieldName}/{path}" + .replace("{" + "path" + "}", getApiClient().escapeString(path.toString())) + .replace("{" + "fieldName" + "}", getApiClient().escapeString(fieldName.toString())) + .replace("{" + "project" + "}", getApiClient().escapeString(project.toString())); + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (fpz != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("fpz", fpz)); + } + + if (rect != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("rect", rect)); + } + + if (w != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("w", w)); + } + + if (h != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("h", h)); + } + + if (resize != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("resize", resize)); + } + + if (version != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("version", version)); + } + + if (fpy != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("fpy", fpy)); + } + + if (crop != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("crop", crop)); + } + + if (fpx != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("fpx", fpx)); + } + + final String[] localVarAccepts = { + }; + final String localVarAccept = getApiClient().selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + }; + final String localVarContentType = getApiClient().selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return getApiClient().buildCall(basePath, localVarPath, "GET", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2OpenapiYamlGetCall(final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = null; + + // create path and map variables + String localVarPath = "/api/v2/openapi.yaml"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + final String[] localVarAccepts = { + "application/x-yaml" + }; + final String localVarAccept = getApiClient().selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + }; + final String localVarContentType = getApiClient().selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return getApiClient().buildCall(basePath, localVarPath, "GET", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + // Fix for no generated body parameter + + public UpgradedCall apiV2UtilitiesLinkResolverPostCall(String body, String lang, String resolveLinks, ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = body; + + // create path and map variables + String localVarPath = "/api/v2/utilities/linkResolver"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (lang != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("lang", lang)); + } + + if (resolveLinks != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("resolveLinks", resolveLinks)); + } + + final String[] localVarAccepts = { + }; + final String localVarAccept = getApiClient().selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "text/plain" + }; + final String localVarContentType = getApiClient().selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + + return getApiClient().buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2ProjectNodesNodeUuidPostCall(@jakarta.annotation.Nonnull String nodeUuid, @jakarta.annotation.Nonnull String project, JsonObject body, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = Optional.ofNullable(body).map(json -> JsonParser.parseString(body.toString()).getAsJsonObject()); + + // create path and map variables + String localVarPath = "/api/v2/{project}/nodes/{nodeUuid}" + .replace("{" + "nodeUuid" + "}", getApiClient().escapeString(nodeUuid.toString())) + .replace("{" + "project" + "}", getApiClient().escapeString(project.toString())); + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + final String[] localVarAccepts = { + "application/json", + "*/*" + }; + final String localVarAccept = getApiClient().selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = getApiClient().selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return getApiClient().buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + // Missing JSON body fix + + public UpgradedCall apiV2SearchNodesPostCall(String jsonbody, @jakarta.annotation.Nullable Boolean wait, @jakarta.annotation.Nullable Double perPage, @jakarta.annotation.Nullable String sortBy, @jakarta.annotation.Nullable Boolean etag, @jakarta.annotation.Nullable Double page, @jakarta.annotation.Nullable String fields, @jakarta.annotation.Nullable String branch, @jakarta.annotation.Nullable String order, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(jsonbody); + + // create path and map variables + String localVarPath = "/api/v2/search/nodes"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (wait != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("wait", wait)); + } + + if (perPage != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("perPage", perPage)); + } + + if (sortBy != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("sortBy", sortBy)); + } + + if (etag != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("etag", etag)); + } + + if (page != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("page", page)); + } + + if (fields != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("fields", fields)); + } + + if (branch != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("branch", branch)); + } + + if (order != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("order", order)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = getApiClient().selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = getApiClient().selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return getApiClient().buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2RawSearchNodesPostCall(String json, @jakarta.annotation.Nullable Boolean wait, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/rawSearch/nodes"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (wait != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("wait", wait)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = getApiClient().selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = getApiClient().selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return getApiClient().buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2ProjectRawSearchNodesPostCall(String json, @jakarta.annotation.Nonnull String project, @jakarta.annotation.Nullable Boolean wait, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/{project}/rawSearch/nodes" + .replace("{" + "project" + "}", getApiClient().escapeString(project.toString())); + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (wait != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("wait", wait)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = getApiClient().selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = getApiClient().selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return getApiClient().buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + public UpgradedCall apiV2RawSearchGroupsPostCall(String json, @jakarta.annotation.Nullable Boolean wait, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = null; + + // create path and map variables + String localVarPath = "/api/v2/rawSearch/groups"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2RawSearchRolesPostCall(String json, @jakarta.annotation.Nullable Boolean wait, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = null; + + // create path and map variables + String localVarPath = "/api/v2/rawSearch/roles"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2RawSearchProjectsPostCall(String json, @jakarta.annotation.Nullable Boolean wait, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/rawSearch/projects"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2RawSearchTagsPostCall(String json, @jakarta.annotation.Nullable Boolean wait, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/rawSearch/tags"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2SearchSchemasPostCall(String json, @jakarta.annotation.Nullable String sortBy, @jakarta.annotation.Nullable Boolean wait, @jakarta.annotation.Nullable Double page, @jakarta.annotation.Nullable Double perPage, @jakarta.annotation.Nullable String order, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/search/schemas"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (sortBy != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("sortBy", sortBy)); + } + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + if (page != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("page", page)); + } + + if (perPage != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("perPage", perPage)); + } + + if (order != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("order", order)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2SearchMicroschemasPostCall(String json, @jakarta.annotation.Nullable String sortBy, @jakarta.annotation.Nullable Boolean wait, @jakarta.annotation.Nullable Double page, @jakarta.annotation.Nullable Double perPage, @jakarta.annotation.Nullable String order, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/search/microschemas"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (sortBy != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("sortBy", sortBy)); + } + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + if (page != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("page", page)); + } + + if (perPage != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("perPage", perPage)); + } + + if (order != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("order", order)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + public UpgradedCall apiV2ProjectSearchTagFamiliesPostCall(String json, @jakarta.annotation.Nonnull String project, @jakarta.annotation.Nullable String sortBy, @jakarta.annotation.Nullable Boolean wait, @jakarta.annotation.Nullable Double page, @jakarta.annotation.Nullable Double perPage, @jakarta.annotation.Nullable String order, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = null; + + // create path and map variables + String localVarPath = "/api/v2/{project}/search/tagFamilies" + .replace("{" + "project" + "}", localVarApiClient.escapeString(project.toString())); + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (sortBy != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("sortBy", sortBy)); + } + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + if (page != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("page", page)); + } + + if (perPage != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("perPage", perPage)); + } + + if (order != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("order", order)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + public UpgradedCall apiV2ProjectSearchTagsPostCall(String json, @jakarta.annotation.Nonnull String project, @jakarta.annotation.Nullable String sortBy, @jakarta.annotation.Nullable Boolean wait, @jakarta.annotation.Nullable Double page, @jakarta.annotation.Nullable Double perPage, @jakarta.annotation.Nullable String order, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/{project}/search/tags" + .replace("{" + "project" + "}", localVarApiClient.escapeString(project.toString())); + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (sortBy != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("sortBy", sortBy)); + } + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + if (page != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("page", page)); + } + + if (perPage != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("perPage", perPage)); + } + + if (order != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("order", order)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + public UpgradedCall apiV2SearchTagsPostCall(String json, @jakarta.annotation.Nullable String sortBy, @jakarta.annotation.Nullable Boolean wait, @jakarta.annotation.Nullable Double page, @jakarta.annotation.Nullable Double perPage, @jakarta.annotation.Nullable String order, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/search/tags"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (sortBy != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("sortBy", sortBy)); + } + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + if (page != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("page", page)); + } + + if (perPage != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("perPage", perPage)); + } + + if (order != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("order", order)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + public UpgradedCall apiV2SearchProjectsPostCall(String json, @jakarta.annotation.Nullable String sortBy, @jakarta.annotation.Nullable Boolean wait, @jakarta.annotation.Nullable Double page, @jakarta.annotation.Nullable Double perPage, @jakarta.annotation.Nullable String order, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/search/projects"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (sortBy != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("sortBy", sortBy)); + } + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + if (page != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("page", page)); + } + + if (perPage != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("perPage", perPage)); + } + + if (order != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("order", order)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + public UpgradedCall apiV2SearchRolesPostCall(String json, @jakarta.annotation.Nullable String sortBy, @jakarta.annotation.Nullable Boolean wait, @jakarta.annotation.Nullable Double page, @jakarta.annotation.Nullable Double perPage, @jakarta.annotation.Nullable String order, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/search/roles"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (sortBy != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("sortBy", sortBy)); + } + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + if (page != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("page", page)); + } + + if (perPage != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("perPage", perPage)); + } + + if (order != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("order", order)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + public UpgradedCall apiV2SearchGroupsPostCall(String json, @jakarta.annotation.Nullable String sortBy, @jakarta.annotation.Nullable Boolean wait, @jakarta.annotation.Nullable Double page, @jakarta.annotation.Nullable Double perPage, @jakarta.annotation.Nullable String order, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = null; + + // create path and map variables + String localVarPath = "/api/v2/search/groups"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (sortBy != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("sortBy", sortBy)); + } + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + if (page != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("page", page)); + } + + if (perPage != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("perPage", perPage)); + } + + if (order != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("order", order)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2ProjectRawSearchTagsPostCall(String json, @jakarta.annotation.Nonnull String project, @jakarta.annotation.Nullable Boolean wait, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/{project}/rawSearch/tags" + .replace("{" + "project" + "}", localVarApiClient.escapeString(project.toString())); + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2ProjectRawSearchTagFamiliesPostCall(String json, @jakarta.annotation.Nonnull String project, @jakarta.annotation.Nullable Boolean wait, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/{project}/rawSearch/tagFamilies" + .replace("{" + "project" + "}", localVarApiClient.escapeString(project.toString())); + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2RawSearchTagFamiliesPostCall(String json, @jakarta.annotation.Nullable Boolean wait, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = null; + + // create path and map variables + String localVarPath = "/api/v2/rawSearch/tagFamilies"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2RawSearchSchemasPostCall(String json, @jakarta.annotation.Nullable Boolean wait, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/rawSearch/schemas"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2RawSearchMicroschemasPostCall(String json, @jakarta.annotation.Nullable Boolean wait, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/rawSearch/microschemas"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2RawSearchUsersPostCall(String json, @jakarta.annotation.Nullable Boolean wait, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/rawSearch/users"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2SearchUsersPostCall(String json, @jakarta.annotation.Nullable String sortBy, @jakarta.annotation.Nullable Boolean wait, @jakarta.annotation.Nullable Double page, @jakarta.annotation.Nullable Double perPage, @jakarta.annotation.Nullable String order, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/search/users"; + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (sortBy != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("sortBy", sortBy)); + } + + if (wait != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("wait", wait)); + } + + if (page != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("page", page)); + } + + if (perPage != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("perPage", perPage)); + } + + if (order != null) { + localVarQueryParams.addAll(localVarApiClient.parameterToPair("order", order)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return localVarApiClient.buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } + + public UpgradedCall apiV2ProjectSearchNodesPostCall(String json, @jakarta.annotation.Nonnull String project, @jakarta.annotation.Nullable Boolean wait, @jakarta.annotation.Nullable Double perPage, @jakarta.annotation.Nullable String sortBy, @jakarta.annotation.Nullable Boolean etag, @jakarta.annotation.Nullable Double page, @jakarta.annotation.Nullable String fields, @jakarta.annotation.Nullable String order, final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { }; + + // Determine Base Path to Use + if (getCustomBaseUrl() != null){ + basePath = getCustomBaseUrl(); + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[getHostIndex()]; + } else { + basePath = null; + } + + Object localVarPostBody = JsonParser.parseString(json); + + // create path and map variables + String localVarPath = "/api/v2/{project}/search/nodes" + .replace("{" + "project" + "}", getApiClient().escapeString(project.toString())); + + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + if (wait != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("wait", wait)); + } + + if (perPage != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("perPage", perPage)); + } + + if (sortBy != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("sortBy", sortBy)); + } + + if (etag != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("etag", etag)); + } + + if (page != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("page", page)); + } + + if (fields != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("fields", fields)); + } + + if (order != null) { + localVarQueryParams.addAll(getApiClient().parameterToPair("order", order)); + } + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = getApiClient().selectHeaderAccept(localVarAccepts); + if (localVarAccept != null) { + localVarHeaderParams.put("Accept", localVarAccept); + } + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = getApiClient().selectHeaderContentType(localVarContentTypes); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } + + String[] localVarAuthNames = new String[] { "bearerAuth" }; + return getApiClient().buildCall(basePath, localVarPath, "POST", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + } +} diff --git a/tests/tests-core/src/main/java/com/gentics/mesh/util/JsonUtilTest.java b/tests/tests-core/src/main/java/com/gentics/mesh/util/JsonUtilTest.java index 7f252183bd..a98752b078 100644 --- a/tests/tests-core/src/main/java/com/gentics/mesh/util/JsonUtilTest.java +++ b/tests/tests-core/src/main/java/com/gentics/mesh/util/JsonUtilTest.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonMappingException; import com.gentics.mesh.FieldUtil; -import com.gentics.mesh.core.rest.common.ListResponse; import com.gentics.mesh.core.rest.common.PermissionInfo; import com.gentics.mesh.core.rest.error.GenericRestException; import com.gentics.mesh.core.rest.graphql.GraphQLResponse; @@ -32,6 +31,7 @@ import com.gentics.mesh.core.rest.schema.impl.MicronodeFieldSchemaImpl; import com.gentics.mesh.core.rest.schema.impl.SchemaResponse; import com.gentics.mesh.core.rest.schema.impl.SchemaUpdateRequest; +import com.gentics.mesh.core.rest.user.UserListResponse; import com.gentics.mesh.core.rest.user.UserResponse; import com.gentics.mesh.example.GraphQLExamples; import com.gentics.mesh.json.JsonUtil; @@ -81,7 +81,7 @@ public void testCompareJson() { @Test public void testJsonList() { - ListResponse list = new ListResponse<>(); + UserListResponse list = new UserListResponse(); UserResponse user = new UserResponse(); list.getData().add(user); assertNotNull(list.toJson()); diff --git a/tests/tests-hibernate/src/main/java/com/gentics/mesh/core/AbstractHibernateOptionsProvider.java b/tests/tests-hibernate/src/main/java/com/gentics/mesh/core/AbstractHibernateOptionsProvider.java index 288ceaa13f..bbbcdc2f83 100644 --- a/tests/tests-hibernate/src/main/java/com/gentics/mesh/core/AbstractHibernateOptionsProvider.java +++ b/tests/tests-hibernate/src/main/java/com/gentics/mesh/core/AbstractHibernateOptionsProvider.java @@ -1,5 +1,11 @@ package com.gentics.mesh.core; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.fasterxml.jackson.databind.ObjectMapper; import com.gentics.mesh.OptionsLoader; import com.gentics.mesh.etc.config.HibernateMeshOptions; @@ -7,10 +13,21 @@ public abstract class AbstractHibernateOptionsProvider implements HibernateMeshOptionsProvider { + protected static final Logger log = LoggerFactory.getLogger(AbstractHibernateOptionsProvider.class); + protected final HibernateMeshOptions meshOptions; + @SuppressWarnings("unchecked") public AbstractHibernateOptionsProvider() { - meshOptions = OptionsLoader.createOrloadOptions(HibernateMeshOptions.class, OptionsLoader.generateDefaultConfig(HibernateMeshOptions.class, null)); + Class optionsClass = Optional.ofNullable(System.getProperty(ENV_OPTIONS_CLASS, StringUtils.EMPTY)).filter(StringUtils::isNotBlank).map(cls -> { + try { + return (Class) Class.forName(cls); + } catch (ClassNotFoundException e) { + log.error("Could not instantiate custom options class: " + cls, e); + return HibernateMeshOptions.class; + } + }).orElse(HibernateMeshOptions.class); + meshOptions = OptionsLoader.createOrloadOptions(optionsClass, OptionsLoader.generateDefaultConfig(optionsClass, null)); } @Override @@ -24,7 +41,7 @@ public MeshOptions getClone() throws Exception { ObjectMapper mapper = OptionsLoader.getYAMLMapper(); String optionsAsString = mapper.writeValueAsString(meshOptions); - HibernateMeshOptions clonedMeshOptions = mapper.readValue(optionsAsString, HibernateMeshOptions.class); + HibernateMeshOptions clonedMeshOptions = mapper.readValue(optionsAsString, meshOptions.getClass()); // by actually sharing the storage options, we make sure that if the database connection settings are changed in the original mesh options, // all instances will get the updated settings diff --git a/tests/tests-hibernate/src/main/java/com/gentics/mesh/core/HibernateMeshOptionsProvider.java b/tests/tests-hibernate/src/main/java/com/gentics/mesh/core/HibernateMeshOptionsProvider.java index 88d5717245..36fc9d8a68 100644 --- a/tests/tests-hibernate/src/main/java/com/gentics/mesh/core/HibernateMeshOptionsProvider.java +++ b/tests/tests-hibernate/src/main/java/com/gentics/mesh/core/HibernateMeshOptionsProvider.java @@ -3,7 +3,12 @@ import com.gentics.mesh.etc.config.HibernateMeshOptions; import com.gentics.mesh.test.MeshOptionsProvider; +/** + * An extension to the {@link MeshOptionsProvider} to customize options class and instance. + */ public interface HibernateMeshOptionsProvider extends MeshOptionsProvider { + + public static final String ENV_OPTIONS_CLASS = "optionsClass"; void fillMeshOptions(HibernateMeshOptions meshOptions); }