Skip to content

Commit

Permalink
Merge branch 'develop' into TASK-7134
Browse files Browse the repository at this point in the history
  • Loading branch information
juanfeSanahuja authored Feb 10, 2025
2 parents 51e7fa2 + 8197675 commit be93358
Show file tree
Hide file tree
Showing 19 changed files with 939 additions and 27 deletions.
7 changes: 7 additions & 0 deletions opencga-client/src/main/R/R/Meta-methods.R
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#' | api | /{apiVersion}/meta/api | category |
#' | fail | /{apiVersion}/meta/fail | |
#' | model | /{apiVersion}/meta/model | model |
#' | openapi | /{apiVersion}/meta/openapi | token |
#' | ping | /{apiVersion}/meta/ping | |
#' | status | /{apiVersion}/meta/status | |
#'
Expand Down Expand Up @@ -59,6 +60,12 @@ setMethod("metaClient", "OpencgaR", function(OpencgaR, endpointName, params=NULL
model=fetchOpenCGA(object=OpencgaR, category="meta", categoryId=NULL, subcategory=NULL, subcategoryId=NULL,
action="model", params=params, httpMethod="GET", as.queryParam=NULL, ...),

#' @section Endpoint /{apiVersion}/meta/openapi:
#' Opencga openapi json.
#' @param token List of categories to get API from.
openapi=fetchOpenCGA(object=OpencgaR, category="meta", categoryId=NULL, subcategory=NULL, subcategoryId=NULL,
action="openapi", params=params, httpMethod="GET", as.queryParam=NULL, ...),

#' @section Endpoint /{apiVersion}/meta/ping:
#' Ping Opencga webservices.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ public RestResponse<String> model(ObjectMap params) throws ClientException {
return execute("meta", null, null, null, "model", params, GET, String.class);
}

/**
* Opencga openapi json.
* @param params Map containing any of the following optional parameters.
* token: List of categories to get API from.
* @return a RestResponse object.
* @throws ClientException ClientException if there is any server error.
*/
public RestResponse<String> openapi(ObjectMap params) throws ClientException {
params = params != null ? params : new ObjectMap();
return execute("meta", null, null, null, "openapi", params, GET, String.class);
}

/**
* Ping Opencga webservices.
* @return a RestResponse object.
Expand Down
9 changes: 9 additions & 0 deletions opencga-client/src/main/javascript/Meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,15 @@ export default class Meta extends OpenCGAParentClass {
return this._get("meta", null, null, null, "model", params);
}

/** Opencga openapi json
* @param {Object} [params] - The Object containing the following optional parameters:
* @param {String} [params.token] - List of categories to get API from.
* @returns {Promise} Promise object in the form of RestResponse instance.
*/
openapi(params) {
return this._get("meta", null, null, null, "openapi", params);
}

/** Ping Opencga webservices.
*
* @returns {Promise} Promise object in the form of RestResponse instance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ def model(self, **options):

return self._get(category='meta', resource='model', **options)

def openapi(self, **options):
"""
Opencga openapi json.
PATH: /{apiVersion}/meta/openapi
:param str token: List of categories to get API from.
"""

return self._get(category='meta', resource='openapi', **options)

def ping(self, **options):
"""
Ping Opencga webservices.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,12 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.apache.logging.log4j.core.config.Configurator;
import org.opencb.opencga.server.generator.commons.ApiCommonsImpl;
import org.opencb.opencga.server.generator.config.CommandLineConfiguration;
import org.opencb.opencga.server.generator.models.RestApi;
import org.opencb.opencga.server.generator.models.RestCategory;
import org.opencb.opencga.server.generator.models.RestEndpoint;
import org.opencb.opencga.server.generator.models.RestParameter;
import org.opencb.opencga.server.rest.*;
import org.opencb.opencga.server.rest.admin.AdminWSServer;
import org.opencb.opencga.server.rest.analysis.AlignmentWebService;
import org.opencb.opencga.server.rest.analysis.ClinicalWebService;
import org.opencb.opencga.server.rest.analysis.VariantWebService;
import org.opencb.opencga.server.rest.ga4gh.Ga4ghWSServer;
import org.opencb.opencga.server.rest.operations.VariantOperationWebService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -32,26 +26,8 @@ public static void main(String[] args) throws URISyntaxException {
System.setProperty("opencga.log.file.enabled", "false");
System.setProperty("opencga.log.level", "info");
Configurator.reconfigure();

List<Class<?>> classes = new ArrayList<>();
classes.add(OrganizationWSServer.class);
classes.add(UserWSServer.class);
classes.add(ProjectWSServer.class);
classes.add(StudyWSServer.class);
classes.add(FileWSServer.class);
classes.add(JobWSServer.class);
classes.add(SampleWSServer.class);
classes.add(IndividualWSServer.class);
classes.add(FamilyWSServer.class);
classes.add(CohortWSServer.class);
classes.add(PanelWSServer.class);
classes.add(AlignmentWebService.class);
classes.add(VariantWebService.class);
classes.add(ClinicalWebService.class);
classes.add(VariantOperationWebService.class);
classes.add(MetaWSServer.class);
classes.add(Ga4ghWSServer.class);
classes.add(AdminWSServer.class);
ApiCommonsImpl apiCommons = new ApiCommonsImpl();
List<Class<?>> classes = apiCommons.getApiClasses();

try {
// Create CommandLineConfiguration and ClientsGenerator
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.opencb.opencga.server.generator.commons;

import java.util.List;

public interface ApiCommons {

public List<Class<?>> getApiClasses();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.opencb.opencga.server.generator.commons;

import org.opencb.opencga.server.rest.*;
import org.opencb.opencga.server.rest.admin.AdminWSServer;
import org.opencb.opencga.server.rest.analysis.AlignmentWebService;
import org.opencb.opencga.server.rest.analysis.ClinicalWebService;
import org.opencb.opencga.server.rest.analysis.VariantWebService;
import org.opencb.opencga.server.rest.ga4gh.Ga4ghWSServer;
import org.opencb.opencga.server.rest.operations.VariantOperationWebService;

import java.util.ArrayList;
import java.util.List;

public class ApiCommonsImpl implements ApiCommons {

public List<Class<?>> getApiClasses(){
List<Class<?>> classes = new ArrayList<>();
classes.add(OrganizationWSServer.class);
classes.add(UserWSServer.class);
classes.add(ProjectWSServer.class);
classes.add(StudyWSServer.class);
classes.add(FileWSServer.class);
classes.add(JobWSServer.class);
classes.add(SampleWSServer.class);
classes.add(IndividualWSServer.class);
classes.add(FamilyWSServer.class);
classes.add(CohortWSServer.class);
classes.add(PanelWSServer.class);
classes.add(AlignmentWebService.class);
classes.add(VariantWebService.class);
classes.add(ClinicalWebService.class);
classes.add(VariantOperationWebService.class);
classes.add(MetaWSServer.class);
classes.add(Ga4ghWSServer.class);
classes.add(AdminWSServer.class);

return classes;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
package org.opencb.opencga.server.generator.openapi;
import org.apache.commons.lang3.StringUtils;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.opencb.opencga.core.common.GitRepositoryState;
import org.opencb.opencga.core.tools.annotations.*;
import org.opencb.opencga.server.generator.commons.ApiCommons;
import org.opencb.opencga.server.generator.models.RestParameter;
import org.opencb.opencga.server.generator.openapi.models.*;
import org.opencb.opencga.server.generator.openapi.common.SwaggerDefinitionGenerator;

import javax.ws.rs.*;
import java.util.*;

public class JsonOpenApiGenerator {

public Swagger generateJsonOpenApi(ApiCommons apiCommons, String token, String environment) {
List<Class<?>> classes = apiCommons.getApiClasses();
List<Class<?>> beansDefinitions= new ArrayList<>();
Swagger swagger = new Swagger();
Info info = new Info();
info.setTitle("OpenCGA RESTful Web Services");
info.setDescription("OpenCGA RESTful Web Services API");
info.setVersion(GitRepositoryState.getInstance().getBuildVersion());
swagger.setInfo(info);
swagger.setHost("test.app.zettagenomics.com");
swagger.setBasePath(environment + "/opencga/webservices/rest");
List<String> schemes = new ArrayList<>();
schemes.add("https");
swagger.setSchemes(schemes);
Map<String, Map<String, Method>> paths = new HashMap<>();
List<Tag> tags = new ArrayList<>();

// Configuración del esquema Bearer
Map<String, Map<String, Object>> securityDefinitions = new HashMap<>();
Map<String, Object> bearerAuth = new HashMap<>();
bearerAuth.put("type", "apiKey");
bearerAuth.put("name", "Authorization");
bearerAuth.put("in", "header");
bearerAuth.put("description", "Use 'Bearer <token>' to authenticate");
securityDefinitions.put("BearerAuth", bearerAuth);
swagger.setSecurityDefinitions(securityDefinitions);
for (Class<?> clazz : classes) {
Api api = clazz.getAnnotation(Api.class);
if (api == null) {
continue;
}
tags.add(new Tag(api.value(), api.description()));

// Obtener ruta base de la clase
javax.ws.rs.Path classPathAnnotation = clazz.getAnnotation(javax.ws.rs.Path.class);
String basePath = classPathAnnotation.value();
if (classPathAnnotation == null) {
continue;
}

// Procesar métodos
for (java.lang.reflect.Method wsmethod : clazz.getDeclaredMethods()) {
ApiOperation apiOperation = wsmethod.getAnnotation(ApiOperation.class);
if (apiOperation != null) {
// Crear operación Swagger
Method method = new Method();
method.setSummary(apiOperation.value());
method.setDescription(apiOperation.notes());
method.setTags(Collections.singletonList(api.value()));
Map<String,Object> responses=new HashMap<>();
responses.put("type", String.valueOf(apiOperation.response()));
if(apiOperation.response() instanceof Class){
beansDefinitions.add((Class) apiOperation.response());
}
method.getResponses().put("200", responses);

// Obtener el método HTTP
String httpMethod = extractHttpMethod(wsmethod);
if (httpMethod == null) continue;
Consumes consumes = wsmethod.getAnnotation(Consumes.class);

// Extraer parámetros
List<Parameter> parameters = extractParameters(wsmethod, token);
method.setParameters(parameters);
if (consumes != null){
method.getConsumes().addAll(Arrays.asList(consumes.value()));
}
method.getProduces().add("application/json");

// Ruta completa del endpoint
javax.ws.rs.Path methodPathAnnotation = wsmethod.getAnnotation(javax.ws.rs.Path.class);
String fullPath = basePath + (methodPathAnnotation != null ? methodPathAnnotation.value() : "");
method.setOperationId(methodPathAnnotation != null ? methodPathAnnotation.value() : "");
List tokens = new ArrayList<>();
if(!StringUtils.isEmpty(token)){
tokens.add("Bearer "+token);
}
method.setSecurity(Collections.singletonList(Collections.singletonMap("BearerAuth", tokens)));

// Crear o actualizar el Path
paths.put(fullPath, new HashMap<>());
paths.get(fullPath).put(httpMethod, method);
}
}
}
Map<String, Definition> definitions = SwaggerDefinitionGenerator.getDefinitions(beansDefinitions);
swagger.setTags(tags);
swagger.setPaths(paths);
swagger.setDefinitions(definitions);
return swagger;
}

private String extractHttpMethod(java.lang.reflect.Method method) {
if (method.isAnnotationPresent(GET.class)) {
return "get";
} else if (method.isAnnotationPresent(POST.class)) {
return "post";
} else if (method.isAnnotationPresent(PUT.class)) {
return "put";
} else if (method.isAnnotationPresent(DELETE.class)) {
return "delete";
}
return null;
}

private List<Parameter> extractParameters(java.lang.reflect.Method method, String token) {
List<Parameter> parameters = new ArrayList<>();

// Procesar parámetros definidos con @ApiImplicitParams
ApiImplicitParams implicitParams = method.getAnnotation(ApiImplicitParams.class);
if (implicitParams != null) {
for (ApiImplicitParam implicitParam : implicitParams.value()) {
Parameter parameter = new Parameter();
parameter.setName(implicitParam.name());
parameter.setIn(implicitParam.paramType());
parameter.setDescription(implicitParam.value());
parameter.setRequired(implicitParam.required());
parameter.setType(implicitParam.dataType());
parameter.setFormat(implicitParam.format());
parameter.setDefaultValue(implicitParam.defaultValue());
parameters.add(parameter);
}
}

// Procesar parámetros individuales del método
for (java.lang.reflect.Parameter methodParam : method.getParameters()) {
// Procesar ApiParam
// 4.1 Ignore all method parameters without @ApiParam annotations
Parameter parameter = new Parameter();
ApiParam apiParam = methodParam.getAnnotation(ApiParam.class);
if (apiParam == null || apiParam.hidden()) {
continue;
}

// Procesar PathParam
PathParam pathParam = methodParam.getAnnotation(PathParam.class);
if (pathParam != null) {
parameter.setName(pathParam.value());
parameter.setDescription(pathParam.value());
parameter.setRequired(true);
parameter.setType(methodParam.getType().getSimpleName().toLowerCase(Locale.ROOT));
}

// Procesar QueryParam
QueryParam queryParam = methodParam.getAnnotation(QueryParam.class);
if (queryParam != null) {
parameter.setName(queryParam.value());
parameter.setDescription(queryParam.value());
parameter.setRequired(apiParam.required());
parameter.setType(methodParam.getType().getSimpleName().toLowerCase(Locale.ROOT));
}

FormDataParam formDataParam = methodParam.getAnnotation(FormDataParam.class);
if (formDataParam != null) {
parameter.setName(formDataParam.value());
parameter.setDescription(formDataParam.value());
parameter.setRequired(apiParam.required());
parameter.setType(methodParam.getType().getSimpleName().toLowerCase(Locale.ROOT));

}
parameter.setIn(getIn(methodParam));
parameter.setDefaultValue(apiParam.defaultValue());
parameter.setDescription(StringUtils.isEmpty(parameter.getDescription())?apiParam.value():parameter.getDescription());
parameters.add(parameter);
}

return parameters;
}

private String getIn(java.lang.reflect.Parameter methodParameter) {
if (methodParameter.getAnnotation(PathParam.class) != null) {
return "path";
} else if (methodParameter.getAnnotation(QueryParam.class) != null
|| methodParameter.getAnnotation(FormDataParam.class) != null) {
return "query";
} else {
return "body";
}
}

/**
* Determina la ubicación del parámetro (query, path, etc.).
*/
private String determineParameterLocation(java.lang.reflect.Parameter parameter) {
if (parameter.isAnnotationPresent(PathParam.class)) {
return "path";
} else if (parameter.isAnnotationPresent(QueryParam.class)) {
return "query";
} else if (parameter.isAnnotationPresent(ApiParam.class)) {
return "query"; // Por defecto si no se especifica
}
return "query"; // Predeterminado
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.opencb.opencga.server.generator.openapi;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.opencb.opencga.server.generator.commons.ApiCommonsImpl;
import org.opencb.opencga.server.generator.openapi.models.Swagger;

public class SwaggerJsonSerializer {
public static void main(String[] args) throws Exception {
JsonOpenApiGenerator generator = new JsonOpenApiGenerator();
Swagger swagger = generator.generateJsonOpenApi(new ApiCommonsImpl(), "El token va aquí", "task-xxxx");

ObjectMapper mapper = new ObjectMapper();
String swaggerJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(swagger);

System.out.println(swaggerJson);
}
}

Loading

0 comments on commit be93358

Please sign in to comment.