/* * Copyright 2015-2016 OpenCB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.opencb.opencga.server.rest.ga4gh; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.ga4gh.methods.SearchReadsRequest; import org.ga4gh.methods.SearchReadsResponse; import org.ga4gh.methods.SearchVariantsRequest; import org.ga4gh.methods.SearchVariantsResponse; import org.ga4gh.models.ReadAlignment; import org.ga4gh.models.Variant; import org.opencb.biodata.models.core.Region; import org.opencb.commons.datastore.core.Query; import org.opencb.commons.datastore.core.QueryOptions; import org.opencb.commons.datastore.core.QueryResult; import org.opencb.opencga.core.exception.VersionException; import org.opencb.opencga.server.rest.OpenCGAWSServer; import org.opencb.opencga.storage.core.alignment.AlignmentDBAdaptor; import org.opencb.opencga.storage.core.manager.AlignmentStorageManager; import org.opencb.opencga.storage.core.manager.variant.VariantStorageManager; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import java.io.IOException; import java.util.List; import static org.opencb.opencga.storage.core.variant.adaptors.VariantDBAdaptor.VariantQueryParams.*; /** * Created on 09/10/15 * * @author Jacobo Coll <jacobo167@gmail.com> */ @Path("/{version}/ga4gh") @Produces(MediaType.APPLICATION_JSON) @Api(value = "GA4GH", position = 13, description = "Global Alliance for Genomics & Health RESTful API") public class Ga4ghWSServer extends OpenCGAWSServer { public Ga4ghWSServer(@Context UriInfo uriInfo, @Context HttpServletRequest httpServletRequest) throws IOException, VersionException { super(uriInfo, httpServletRequest); } /* ================= VARIANTS ===================*/ @POST @Path("/variants/search") @Consumes(MediaType.APPLICATION_JSON) @ApiOperation(value = "Description", position = 1, notes = "Notes") public Response searchVariants(SearchVariantsRequest request) { String method = "ga4gh/variants/search"; try { if (request.getVariantSetId() == null || request.getVariantSetId().isEmpty()) { return createErrorResponse(method, "Required referenceName or referenceId"); } QueryOptions queryOptions = new QueryOptions(uriInfo.getQueryParameters(), true); queryOptions.append(STUDIES.key(), request.getVariantSetId()); // queryOptions.append(, request.getVariantName()); //TODO if (request.getCallSetIds() != null) { queryOptions.append(RETURNED_SAMPLES.key(), request.getCallSetIds()); } CharSequence chr = null; if (request.getReferenceName() != null) { chr = request.getReferenceName(); } if (chr == null) { return createErrorResponse(method, "Required referenceName or referenceId"); } if (request.getStart() == null || request.getStart() < 0) { return createErrorResponse(method, "Required start position"); } if (request.getEnd() == null || request.getEnd() < 0) { return createErrorResponse(method, "Required end position"); } long delta = request.getEnd() - request.getStart(); if (delta < 0/* || delta > 20000*/) { return createErrorResponse(method, "End must be behind the start"); } queryOptions.append(REGION.key(), new Region(chr.toString(), request.getStart().intValue(), request.getEnd().intValue())); if (request.getPageSize() == null || request.getPageSize() <= 0 || request.getPageSize() > 4000) { this.queryOptions.add(QueryOptions.LIMIT, 1000); } else { this.queryOptions.add(QueryOptions.LIMIT, request.getPageSize()); } int page = 0; if (request.getPageToken() != null) { try { page = Integer.parseInt(request.getPageToken().toString()); this.queryOptions.put("skip", this.queryOptions.getInt("limit") * page); } catch (Exception e) { return createErrorResponse(method, "Invalid page token \"" + request.getPageToken() + "\""); } } // Get all query options SearchVariantsResponse response = new SearchVariantsResponse(); Query query = VariantStorageManager.getVariantQuery(queryOptions); List<Variant> variants = variantManager.get(query, queryOptions, sessionId, Variant.class).getResult(); response.setNextPageToken(Integer.toString(++page)); response.setVariants(variants); return buildResponse(Response.ok(response.toString(), MediaType.APPLICATION_JSON_TYPE)); } catch (Exception e) { return createErrorResponse(e); } } /* ================= ALIGNMENTS ===================*/ @POST @Path("/reads/search") @Consumes(MediaType.APPLICATION_JSON) @ApiOperation(value = "Description", position = 1, notes = "Notes") public Response searchAlignments(SearchReadsRequest request) { String method = "ga4gh/reads/search"; try { if (request.getReadGroupIds() == null || request.getReadGroupIds().size() == 0) { return createErrorResponse(method, "Required at least one group id."); } if (request.getReadGroupIds().size() > 1) { return createErrorResponse(method, "Several read group ids yet not supported."); } if (request.getReferenceId() == null || request.getReferenceId().isEmpty()) { return createErrorResponse(method, "Required reference id"); } if (request.getStart() == null || request.getStart() <= 0) { return createErrorResponse(method, "Required start position"); } if (request.getEnd() == null || request.getEnd() <= 0) { return createErrorResponse(method, "Required end position"); } Query query = new Query(); query.put(AlignmentDBAdaptor.QueryParams.REGION.key(), request.getReferenceId() + ":" + request.getStart().intValue() + "-" + request.getEnd().intValue()); this.queryOptions.put(AlignmentDBAdaptor.QueryParams.CONTAINED.key(), true); if (request.getPageSize() == null || request.getPageSize() <= 0 || request.getPageSize() > 4000) { this.queryOptions.put(AlignmentDBAdaptor.QueryParams.LIMIT.key(), 1000); } else { this.queryOptions.put(AlignmentDBAdaptor.QueryParams.LIMIT.key(), request.getPageSize()); } int page = 0; if (request.getPageToken() != null) { try { page = Integer.parseInt(request.getPageToken().toString()); this.queryOptions.put(AlignmentDBAdaptor.QueryParams.SKIP.key(), this.queryOptions.getInt(AlignmentDBAdaptor.QueryParams.LIMIT.key()) * page); } catch (Exception e) { return createErrorResponse(method, "Invalid page token \"" + request.getPageToken() + "\""); } } SearchReadsResponse response = new SearchReadsResponse(); AlignmentStorageManager alignmentStorageManager = new AlignmentStorageManager(catalogManager, storageEngineFactory); QueryResult<ReadAlignment> queryResult = alignmentStorageManager .query("", request.getReadGroupIds().get(0), query, queryOptions, sessionId); response.setAlignments(queryResult.getResult()); response.setNextPageToken(Integer.toString(++page)); return buildResponse(Response.ok(response.toString(), MediaType.APPLICATION_JSON_TYPE)); } catch (Exception e) { return createErrorResponse(e); } } }