/*
* 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;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.opencb.biodata.models.core.Region;
import org.opencb.commons.datastore.core.*;
import org.opencb.opencga.catalog.db.api.FileDBAdaptor;
import org.opencb.opencga.catalog.exceptions.CatalogException;
import org.opencb.opencga.catalog.exceptions.CatalogIOException;
import org.opencb.opencga.catalog.io.CatalogIOManager;
import org.opencb.opencga.catalog.managers.AbstractManager;
import org.opencb.opencga.catalog.managers.CatalogFileUtils;
import org.opencb.opencga.catalog.managers.CatalogManager;
import org.opencb.opencga.catalog.managers.FileManager;
import org.opencb.opencga.catalog.managers.api.IFileManager;
import org.opencb.opencga.catalog.models.DataStore;
import org.opencb.opencga.catalog.models.File;
import org.opencb.opencga.catalog.models.FileIndex;
import org.opencb.opencga.catalog.models.FileTree;
import org.opencb.opencga.catalog.models.acls.permissions.FileAclEntry;
import org.opencb.opencga.catalog.models.acls.permissions.StudyAclEntry;
import org.opencb.opencga.catalog.utils.FileMetadataReader;
import org.opencb.opencga.catalog.utils.FileScanner;
import org.opencb.opencga.core.common.IOUtils;
import org.opencb.opencga.core.common.UriUtils;
import org.opencb.opencga.core.exception.VersionException;
import org.opencb.opencga.storage.core.alignment.AlignmentDBAdaptor;
import org.opencb.opencga.storage.core.alignment.AlignmentStorageEngine;
import org.opencb.opencga.storage.core.exceptions.StorageEngineException;
import org.opencb.opencga.storage.core.manager.variant.VariantStorageManager;
import org.opencb.opencga.storage.core.manager.variant.operations.StorageOperation;
import org.opencb.opencga.storage.core.variant.adaptors.VariantDBAdaptor;
import org.opencb.opencga.storage.core.variant.annotation.VariantAnnotationManager;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.*;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.*;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import static org.opencb.opencga.storage.core.variant.VariantStorageEngine.Options.*;
@Path("/{version}/files")
@Produces(MediaType.APPLICATION_JSON)
@Api(value = "Files", position = 4, description = "Methods for working with 'files' endpoint")
public class FileWSServer extends OpenCGAWSServer {
private IFileManager fileManager;
public FileWSServer(@Context UriInfo uriInfo, @Context HttpServletRequest httpServletRequest) throws IOException,
ClassNotFoundException, IllegalAccessException, InstantiationException, VersionException {
super(uriInfo, httpServletRequest);
fileManager = catalogManager.getFileManager();
}
private static class FileCreateParams {
@JsonProperty(required = true)
public String path;
public String content;
public String description;
@JsonProperty(defaultValue = "false")
public boolean parents;
@JsonProperty(defaultValue = "false")
public boolean directory;
}
@POST
@Path("/create")
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Create file or folder", response = File[].class,
notes = "Creates a file with some content in it or a folder <br>"
+ "<ul>"
+ "<il><b>path</b>: Mandatory parameter. Whole path containing the file or folder name to be created</il><br>"
+ "<il><b>content</b>: Content of the file. Only applicable if <b>directory</b> parameter set to false</il><br>"
+ "<il><b>description</b>: Description of the file or folder to store as metadata.</il><br>"
+ "<il><b>parents</b>: Create the parent directories if they do not exist.</il><br>"
+ "<il><b>directory</b>: Boolean indicating whether to create a file or a directory</il><br>"
+ "<ul>"
)
public Response createFilePOST(@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(name = "params", value = "File parameters", required = true) FileCreateParams params) {
try {
QueryResult<File> file;
if (params.directory) {
// Create directory
file = fileManager.createFolder(studyStr, params.path, new File.FileStatus(File.FileStatus.READY), params.parents,
params.description, queryOptions, sessionId);
} else {
// Create a file
file = fileManager.create(studyStr, File.Type.FILE, File.Format.PLAIN, File.Bioformat.UNKNOWN, params.path, null,
params.description, new File.FileStatus(File.FileStatus.READY), 0, -1, null, -1, null, null, params.parents,
params.content, queryOptions, sessionId);
}
return createOkResponse(file);
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/create-folder")
@ApiOperation(value = "Create a folder in the catalog environment [WARNING]", position = 2, response = File.class,
notes = "WARNING: the usage of this web service is discouraged, please use the POST /create version instead. Be aware that "
+ "this is web service is not tested and this can be deprecated in a future version.")
public Response createFolder(@ApiParam(value = "(DEPRECATED) Use study instead", hidden = true)
@QueryParam("studyId") String studyIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "CSV list of paths where the folders will be created", required = true)
@QueryParam("folders") String folders,
@ApiParam(value = "Paths where the folder will be created", required = true)
@QueryParam("path") String path,
@ApiParam(value = "Create the parent directories if they do not exist")
@QueryParam("parents") @DefaultValue("false") boolean parents) {
try {
if (StringUtils.isNotEmpty(studyIdStr)) {
studyStr = studyIdStr;
}
if (StringUtils.isNotEmpty(path)) {
folders = path;
query.put("folders", folders);
}
long studyId = catalogManager.getStudyId(studyStr, sessionId);
List<String> folderList = Arrays.asList(folders.replace(":", "/").split(","));
List<QueryResult> queryResultList = new ArrayList<>(folderList.size());
for (String folder : folderList) {
try {
java.nio.file.Path folderPath = Paths.get(folder);
QueryResult<File> newFolder = catalogManager.getFileManager().createFolder(Long.toString(studyId), folderPath.toString(),
null, parents, null, queryOptions, sessionId);
newFolder.setId("Create folder");
queryResultList.add(newFolder);
} catch (CatalogException e) {
queryResultList.add(new QueryResult<>("Create folder", -1, 0, 0, "", e.getMessage(), Collections.emptyList()));
}
}
return createOkResponse(queryResultList);
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/{files}/info")
@ApiOperation(value = "File info", position = 3, response = File[].class)
@ApiImplicitParams({
@ApiImplicitParam(name = "include", value = "Fields included in the response, whole JSON path must be provided",
example = "name,attributes", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "exclude", value = "Fields excluded in the response, whole JSON path must be provided",
example = "id,status", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "lazy", value = "False to return entire job and experiment object", defaultValue = "true",
dataType = "boolean", paramType = "query")
})
public Response info(@ApiParam(value="Comma separated list of file ids") @PathParam(value = "files") String fileStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr) {
try {
List<QueryResult<File>> queryResults = new LinkedList<>();
AbstractManager.MyResourceIds resourceIds = fileManager.getIds(fileStr, studyStr, sessionId);
for (Long fileId : resourceIds.getResourceIds()) {
queryResults.add(catalogManager.getFile(fileId, queryOptions, sessionId));
}
return createOkResponse(queryResults);
} catch (Exception e) {
return createErrorResponse(e);
}
}
@Deprecated
@GET
@Path("/{fileId}/uri")
@ApiOperation(value = "File uri [DEPRECATED]", position = 3, notes = "Deprecated method. Use /info with include query options instead.",
hidden = true)
public Response getUri(@ApiParam(value = "fileId") @PathParam(value = "fileId") String fileStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr) {
try {
List<QueryResult> results = new LinkedList<>();
AbstractManager.MyResourceIds resourceIds = fileManager.getIds(fileStr, studyStr, sessionId);
for (long fileId : resourceIds.getResourceIds()) {
System.out.println("fileId = " + fileId);
QueryResult<File> result = catalogManager.getFile(fileId, queryOptions, sessionId);
URI fileUri = result.first().getUri();
results.add(new QueryResult<>(Long.toString(fileId), 0, 1, 1, "", "", Collections.singletonList(fileUri)));
}
return createOkResponse(results);
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/bioformats")
@ApiOperation(value = "List of accepted file bioformats", position = 3)
public Response getBioformats() {
List<File.Bioformat> bioformats = Arrays.asList(File.Bioformat.values());
QueryResult<File.Bioformat> queryResult = new QueryResult("Bioformats", 0, bioformats.size(), bioformats.size(), "", "", bioformats);
return createOkResponse(queryResult);
}
@GET
@Path("/formats")
@ApiOperation(value = "List of accepted file formats", position = 3)
public Response getFormats() {
List<File.Format> formats = Arrays.asList(File.Format.values());
QueryResult<File.Format> queryResult = new QueryResult("Formats", 0, formats.size(), formats.size(), "", "", formats);
return createOkResponse(queryResult);
}
@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@ApiOperation(httpMethod = "POST", position = 4, value = "Resource to upload a file by chunks", response = File.class)
public Response upload(@ApiParam(hidden = true) @FormDataParam("chunk_content") byte[] chunkBytes,
@ApiParam(hidden = true) @FormDataParam("chunk_content") FormDataContentDisposition contentDisposition,
@FormDataParam("file") InputStream fileInputStream,
@FormDataParam("file") FormDataContentDisposition fileMetaData,
@ApiParam(hidden = true) @DefaultValue("") @FormDataParam("chunk_id") String chunk_id,
@ApiParam(hidden = true) @DefaultValue("false") @FormDataParam("last_chunk") String last_chunk,
@ApiParam(hidden = true) @DefaultValue("") @FormDataParam("chunk_total") String chunk_total,
@ApiParam(hidden = true) @DefaultValue("") @FormDataParam("chunk_size") String chunk_size,
@ApiParam(hidden = true) @DefaultValue("") @FormDataParam("chunk_hash") String chunkHash,
@ApiParam(hidden = true) @DefaultValue("false") @FormDataParam("resume_upload") String resume_upload,
@ApiParam(value = "filename", required = false) @FormDataParam("filename") String filename,
@ApiParam(value = "fileFormat", required = true) @DefaultValue("") @FormDataParam("fileFormat")
String fileFormat,
@ApiParam(value = "bioformat", required = true) @DefaultValue("") @FormDataParam("bioformat")
String bioformat,
@ApiParam(value = "(DEPRECATED) Use study instead", hidden = true) @FormDataParam("studyId")
String studyIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@FormDataParam("study") String studyStr,
@ApiParam(value = "Path within catalog where the file will be located (default: root folder)",
required = true) @DefaultValue(".") @FormDataParam("relativeFilePath") String relativeFilePath,
@ApiParam(value = "description", required = false) @DefaultValue("") @FormDataParam("description")
String description,
@ApiParam(value = "Create the parent directories if they do not exist", required = false)
@DefaultValue("true") @FormDataParam("parents") boolean parents) {
if (StringUtils.isNotEmpty(studyIdStr)) {
studyStr = studyIdStr;
}
try {
File.Format.valueOf(fileFormat.toUpperCase());
} catch (IllegalArgumentException e) {
return createErrorResponse(new CatalogException("The file format " + fileFormat + " introduced is not valid."));
}
try {
File.Bioformat.valueOf(bioformat.toUpperCase());
} catch (IllegalArgumentException e) {
return createErrorResponse(new CatalogException("The file bioformat " + bioformat + " introduced is not valid."));
}
long t = System.currentTimeMillis();
if (relativeFilePath.endsWith("/")) {
relativeFilePath = relativeFilePath.substring(0, relativeFilePath.length() - 1);
}
if (relativeFilePath.startsWith("/")) {
return createErrorResponse(new CatalogException("The path cannot be absolute"));
}
java.nio.file.Path filePath = null;
final long studyId;
try {
studyId = catalogManager.getStudyId(studyStr, sessionId);
String userId = catalogManager.getUserManager().getId(sessionId);
catalogManager.getAuthorizationManager().checkStudyPermission(studyId, userId, StudyAclEntry.StudyPermissions.UPLOAD_FILES);
// TODO: Improve upload method. Check upload permission not only at study level.
} catch (Exception e) {
return createErrorResponse(e);
}
try {
filePath = Paths.get(catalogManager.getFileUri(studyId, relativeFilePath));
System.out.println(filePath);
} catch (CatalogIOException e) {
System.out.println("catalogManager.getFilePath");
e.printStackTrace();
} catch (CatalogException e) {
e.printStackTrace();
}
if (chunkBytes != null) {
java.nio.file.Path completedFilePath = filePath.getParent().resolve("_" + filename);
java.nio.file.Path folderPath = filePath.getParent().resolve("__" + filename);
logger.info(relativeFilePath + "");
logger.info(folderPath + "");
logger.info(filePath + "");
boolean resume = Boolean.parseBoolean(resume_upload);
try {
logger.info("---resume is: " + resume);
if (resume) {
logger.info("Resume ms :" + (System.currentTimeMillis() - t));
return createOkResponse(getResumeFileJSON(folderPath));
}
int chunkId = Integer.parseInt(chunk_id);
int chunkSize = Integer.parseInt(chunk_size);
boolean lastChunk = Boolean.parseBoolean(last_chunk);
logger.info("---saving chunk: " + chunkId);
logger.info("lastChunk: " + lastChunk);
// WRITE CHUNK TYPE_FILE
if (!Files.exists(folderPath)) {
logger.info("createDirectory(): " + folderPath);
Files.createDirectory(folderPath);
}
logger.info("check dir " + Files.exists(folderPath));
// String hash = StringUtils.sha1(new String(chunkBytes));
// logger.info("bytesHash: " + hash);
// logger.info("chunkHash: " + chunkHash);
// hash = chunkHash;
if (chunkBytes.length == chunkSize) {
Files.write(folderPath.resolve(chunkId + "_" + chunkBytes.length + "_partial"), chunkBytes);
} else {
String errorMessage = "Chunk content size (" + chunkBytes.length + ") " +
"!= chunk_size (" + chunk_size + ").";
logger.error(errorMessage);
return createErrorResponse(new IOException(errorMessage));
}
if (lastChunk) {
logger.info("lastChunk is true...");
Files.deleteIfExists(completedFilePath);
Files.createFile(completedFilePath);
List<java.nio.file.Path> chunks = getSortedChunkList(folderPath);
logger.info("----ordered chunks length: " + chunks.size());
for (java.nio.file.Path partPath : chunks) {
logger.info(partPath.getFileName().toString());
Files.write(completedFilePath, Files.readAllBytes(partPath), StandardOpenOption.APPEND);
}
IOUtils.deleteDirectory(folderPath);
try {
QueryResult<File> queryResult = catalogManager.createFile(studyId, File.Format.valueOf(fileFormat.toUpperCase()),
File.Bioformat.valueOf(bioformat.toUpperCase()), relativeFilePath, completedFilePath.toUri(), description,
parents, sessionId);
File file = new FileMetadataReader(catalogManager).setMetadataInformation(queryResult.first(), null,
new QueryOptions(queryOptions), sessionId, false);
queryResult.setResult(Collections.singletonList(file));
return createOkResponse(queryResult);
} catch (Exception e) {
logger.error(e.toString());
return createErrorResponse(e);
}
}
} catch (IOException e) {
System.out.println("e = " + e);
// TODO Auto-generated catch block
e.printStackTrace();
}
logger.info("chunk saved ms :" + (System.currentTimeMillis() - t));
return createOkResponse("ok");
} else if (fileInputStream != null) {
logger.info("filePath: {}", filePath.toString());
// We obtain the basic studyPath where we will upload the file temporarily
java.nio.file.Path studyPath = null;
try {
studyPath = Paths.get(catalogManager.getStudyUri(studyId));
} catch (CatalogException e) {
e.printStackTrace();
return createErrorResponse("Upload file", e.getMessage());
}
if (filename == null) {
filename = fileMetaData.getFileName();
}
java.nio.file.Path tempFilePath = studyPath.resolve("tmp_" + filename).resolve(filename);
logger.info("tempFilePath: {}", tempFilePath.toString());
logger.info("tempParent: {}", tempFilePath.getParent().toString());
// Create the temporal directory and upload the file
try {
if (!Files.exists(tempFilePath.getParent())) {
logger.info("createDirectory(): " + tempFilePath.getParent());
Files.createDirectory(tempFilePath.getParent());
}
logger.info("check dir " + Files.exists(tempFilePath.getParent()));
// Start uploading the file to the temporal directory
int read;
byte[] bytes = new byte[1024];
// Upload the file to a temporary folder
OutputStream out = new FileOutputStream(new java.io.File(tempFilePath.toString()));
while ((read = fileInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
// Register the file in catalog
try {
String destinationPath;
// Check if the relativeFilePath is not the root folder
if (relativeFilePath.length() > 1 && !relativeFilePath.equals("./")) {
try {
// Create parents directory if necessary
catalogManager.getFileManager().createFolder(Long.toString(studyId), Paths.get(relativeFilePath).toString(),
null, parents, null, QueryOptions.empty(), sessionId);
} catch (CatalogException e) {
logger.debug("The folder {} already exists", relativeFilePath);
}
destinationPath = Paths.get(relativeFilePath).resolve(filename).toString();
} else {
destinationPath = filename;
}
logger.debug("Relative path: {}", relativeFilePath);
logger.debug("Destination path: {}", destinationPath);
logger.debug("File name {}", filename);
logger.debug("Bioformat {}", bioformat);
logger.debug("Fileformat {}", fileFormat);
// Register the file and move it to the proper directory
QueryResult<File> queryResult = catalogManager.createFile(studyId, File.Format.valueOf(fileFormat.toUpperCase()),
File.Bioformat.valueOf(bioformat.toUpperCase()), destinationPath, tempFilePath.toUri(), description, parents,
sessionId);
File file = new FileMetadataReader(catalogManager).setMetadataInformation(queryResult.first(), null,
new QueryOptions(queryOptions), sessionId, false);
queryResult.setResult(Collections.singletonList(file));
// Remove the temporal directory
Files.delete(tempFilePath.getParent());
return createOkResponse(queryResult);
} catch (CatalogException e) {
e.printStackTrace();
return createErrorResponse("Upload file", e.getMessage());
} catch (IOException e) {
e.printStackTrace();
return createErrorResponse("Upload file", e.getMessage());
}
} else {
return createErrorResponse("Upload file", "No file or chunk found");
}
}
@GET
@Path("/{file}/download")
@ApiOperation(value = "Download file", position = 5, response = QueryResponse.class)
public Response download(@ApiParam(value = "File id") @PathParam("file") String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr) {
try {
DataInputStream stream;
AbstractManager.MyResourceId resource = fileManager.getId(fileIdStr, studyStr, sessionId);
catalogManager.getAuthorizationManager().checkFilePermission(resource.getResourceId(), resource.getUser(),
FileAclEntry.FilePermissions.DOWNLOAD);
QueryResult<File> queryResult = catalogManager.getFile(resource.getResourceId(), this.queryOptions, sessionId);
File file = queryResult.getResult().get(0);
stream = catalogManager.downloadFile(resource.getResourceId(), sessionId);
return createOkResponse(stream, MediaType.APPLICATION_OCTET_STREAM_TYPE, file.getName());
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/{file}/content")
@ApiOperation(value = "Show the content of a file (up to a limit)", position = 6, response = String.class)
public Response content(@ApiParam(value = "File id") @PathParam("file") String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "start", required = false) @QueryParam("start") @DefaultValue("-1") int start,
@ApiParam(value = "limit", required = false) @QueryParam("limit") @DefaultValue("-1") int limit) {
try {
AbstractManager.MyResourceId resource = fileManager.getId(fileIdStr, studyStr, sessionId);
catalogManager.getAuthorizationManager().checkFilePermission(resource.getResourceId(), resource.getUser(),
FileAclEntry.FilePermissions.VIEW_CONTENT);
DataInputStream stream = catalogManager.downloadFile(resource.getResourceId(), start, limit, sessionId);
// String content = org.apache.commons.io.IOUtils.toString(stream);
return createOkResponse(stream, MediaType.TEXT_PLAIN_TYPE);
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/{file}/grep")
@ApiOperation(value = "Filter lines of the file containing a match of the pattern [TOCHECK]", position = 7, response = String.class)
public Response downloadGrep(
@ApiParam(value = "File id") @PathParam("file") String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "Pattern", required = false) @QueryParam("pattern") @DefaultValue(".*") String pattern,
@ApiParam(value = "Do a case insensitive search", required = false) @DefaultValue("false") @QueryParam("ignoreCase")
Boolean ignoreCase,
@ApiParam(value = "Return multiple matches", required = false) @DefaultValue("true") @QueryParam("multi") Boolean multi) {
try {
AbstractManager.MyResourceId resource = fileManager.getId(fileIdStr, studyStr, sessionId);
catalogManager.getAuthorizationManager().checkFilePermission(resource.getResourceId(), resource.getUser(),
FileAclEntry.FilePermissions.VIEW_CONTENT);
DataInputStream stream = catalogManager.grepFile(resource.getResourceId(), pattern, ignoreCase, multi, sessionId);
return createOkResponse(stream, MediaType.TEXT_PLAIN_TYPE);
} catch (Exception e) {
return createErrorResponse(e);
}
}
@Deprecated
@GET
@Path("/{file}/set-header")
@ApiOperation(value = "Set file header [DEPRECATED]", position = 10, notes = "Deprecated method. Moved to update.", hidden = true)
public Response setHeader(@PathParam(value = "file") @FormDataParam("fileId") String fileStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "header", required = true) @DefaultValue("") @QueryParam("header") String header) {
String content = "";
DataInputStream stream;
QueryResult<File> fileQueryResult;
InputStream streamBody = null;
try {
AbstractManager.MyResourceId resource = fileManager.getId(fileStr, studyStr, sessionId);
catalogManager.getAuthorizationManager().checkFilePermission(resource.getResourceId(), resource.getUser(),
FileAclEntry.FilePermissions.WRITE);
/** Obtain file uri **/
File file = catalogManager.getFile(resource.getResourceId(), sessionId).getResult().get(0);
URI fileUri = catalogManager.getFileUri(file);
System.out.println("getUri: " + fileUri.getPath());
/** Set header **/
stream = catalogManager.downloadFile(resource.getResourceId(), sessionId);
content = org.apache.commons.io.IOUtils.toString(stream);
String lines[] = content.split(System.getProperty("line.separator"));
StringBuilder body = new StringBuilder();
body.append(header);
body.append(System.getProperty("line.separator"));
for (int i = 0; i < lines.length; i++) {
String line = lines[i];
if (!line.startsWith("#")) {
body.append(line);
if (i != lines.length - 1)
body.append(System.getProperty("line.separator"));
}
}
/** Write/Copy file **/
streamBody = new ByteArrayInputStream(body.toString().getBytes(StandardCharsets.UTF_8));
Files.copy(streamBody, Paths.get(fileUri), StandardCopyOption.REPLACE_EXISTING);
} catch (Exception e) {
return createErrorResponse(e);
}
// createOkResponse(content, MediaType.TEXT_PLAIN)
return createOkResponse(streamBody, MediaType.TEXT_PLAIN_TYPE);
}
@Deprecated
@GET
@Path("/{folder}/files")
@ApiOperation(value = "File content [DEPRECATED]", position = 11, notes = "Deprecated method. Moved to /list.", hidden = true)
@ApiImplicitParams({
@ApiImplicitParam(name = "include", value = "Fields included in the response, whole JSON path must be provided",
example = "name,attributes", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "exclude", value = "Fields excluded in the response, whole JSON path must be provided",
example = "id,status", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "limit", value = "Number of results to be returned in the queries", dataType = "integer",
paramType = "query"),
@ApiImplicitParam(name = "skip", value = "Number of results to skip in the queries", dataType = "integer", paramType = "query")
})
public Response getAllFilesInFolder(@PathParam(value = "folder") @FormDataParam("folderId") String folderStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or "
+ "alias") @QueryParam("study") String studyStr) {
QueryResult<File> results;
try {
long folderId = catalogManager.getFileId(folderStr, studyStr, sessionId);
results = catalogManager.getAllFilesInFolder(folderId, queryOptions, sessionId);
} catch (Exception e) {
return createErrorResponse(e);
}
return createOkResponse(results);
}
@GET
@Path("/search")
@ApiOperation(value = "Multi-study search that allows the user to look for files from from different studies of the same project " +
"applying filters.", position = 12, response = File[].class)
@ApiImplicitParams({
@ApiImplicitParam(name = "include", value = "Fields included in the response, whole JSON path must be provided", example = "name,attributes", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "exclude", value = "Fields excluded in the response, whole JSON path must be provided", example = "id,status", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "limit", value = "Number of results to be returned in the queries", dataType = "integer", paramType = "query"),
@ApiImplicitParam(name = "skip", value = "Number of results to skip in the queries", dataType = "integer", paramType = "query"),
@ApiImplicitParam(name = "count", value = "Total number of results", dataType = "boolean", paramType = "query"),
@ApiImplicitParam(name = "lazy", value = "False to return entire job and experiment object", defaultValue = "true",
dataType = "boolean", paramType = "query")
})
public Response search(@ApiParam(value = "Comma separated list of file ids", required = false) @DefaultValue("") @QueryParam("id") String id,
@ApiParam(value = "(DEPRECATED) Use study instead", hidden = true) @QueryParam("studyId")
String studyIdStr,
@ApiParam(value = "Study [[user@]project:]{study1,study2|*} where studies and project can be either the id or"
+ " alias.") @QueryParam("study") String studyStr,
@ApiParam(value = "Comma separated list of file names") @DefaultValue("") @QueryParam("name") String name,
@ApiParam(value = "Comma separated list of paths", required = false) @DefaultValue("") @QueryParam("path") String path,
@ApiParam(value = "Available types (FILE, DIRECTORY)", required = false) @DefaultValue("") @QueryParam("type") String type,
@ApiParam(value = "Comma separated Bioformat values. For existing Bioformats see files/help", required = false) @DefaultValue("") @QueryParam("bioformat") String bioformat,
@ApiParam(value = "Comma separated Format values. For existing Formats see files/help", required = false) @DefaultValue("") @QueryParam("format") String formats,
@ApiParam(value = "Status", required = false) @DefaultValue("") @QueryParam("status") String status,
@ApiParam(value = "Directory under which we want to look for files or folders", required = false) @DefaultValue("") @QueryParam("directory") String directory,
@ApiParam(value = "Creation date (Format: yyyyMMddHHmmss)", required = false) @DefaultValue("") @QueryParam("creationDate") String creationDate,
@ApiParam(value = "Modification date (Format: yyyyMMddHHmmss)", required = false) @DefaultValue("") @QueryParam("modificationDate") String modificationDate,
@ApiParam(value = "Description", required = false) @DefaultValue("") @QueryParam("description") String description,
@ApiParam(value = "Size", required = false) @DefaultValue("") @QueryParam("size") Long size,
@ApiParam(value = "DEPRECATED: use sample instead", hidden = true) @DefaultValue("") @QueryParam("sampleIds") String sampleIds,
@ApiParam(value = "Comma separated list of sample ids", required = false) @DefaultValue("") @QueryParam("sample") String samples,
@ApiParam(value = "(DEPRECATED) Job id that created the file(s) or folder(s)", hidden = true) @QueryParam("jobId") String jobIdOld,
@ApiParam(value = "Job id that created the file(s) or folder(s)", required = false) @QueryParam("job.id") String jobId,
@ApiParam(value = "Text attributes (Format: sex=male,age>20 ...)", required = false) @DefaultValue("") @QueryParam("attributes") String attributes,
@ApiParam(value = "Numerical attributes (Format: sex=male,age>20 ...)", required = false) @DefaultValue("")
@QueryParam("nattributes") String nattributes,
@ApiParam(value = "Skip count", defaultValue = "false") @QueryParam("skipCount") boolean skipCount) {
try {
queryOptions.put(QueryOptions.SKIP_COUNT, skipCount);
if (StringUtils.isNotEmpty(studyIdStr)) {
studyStr = studyIdStr;
}
if (StringUtils.isNotEmpty(samples)) {
query.put("sampleIds", samples);
}
if (query.containsKey(FileDBAdaptor.QueryParams.NAME.key())
&& (query.get(FileDBAdaptor.QueryParams.NAME.key()) == null
|| query.getString(FileDBAdaptor.QueryParams.NAME.key()).isEmpty())) {
query.remove(FileDBAdaptor.QueryParams.NAME.key());
logger.debug("Name attribute empty, it's been removed");
}
// TODO: jobId is deprecated. Remember to remove this if after next release
if (query.containsKey("jobId") && !query.containsKey(FileDBAdaptor.QueryParams.JOB_ID.key())) {
query.put(FileDBAdaptor.QueryParams.JOB_ID.key(), query.get("jobId"));
query.remove("jobId");
}
QueryResult<File> result = fileManager.search(studyStr, query, queryOptions, sessionId);
return createOkResponse(result);
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/{folder}/list")
@ApiOperation(value = "List all the files inside the folder", position = 13, response = File[].class)
@ApiImplicitParams({
@ApiImplicitParam(name = "include", value = "Fields included in the response, whole JSON path must be provided", example = "name,attributes", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "exclude", value = "Fields excluded in the response, whole JSON path must be provided", example = "id,status", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "limit", value = "Number of results to be returned in the queries", dataType = "integer", paramType = "query"),
@ApiImplicitParam(name = "skip", value = "Number of results to skip in the queries", dataType = "integer", paramType = "query"),
@ApiImplicitParam(name = "count", value = "Total number of results", dataType = "boolean", paramType = "query")
})
public Response list(@ApiParam(value = "Folder id") @PathParam("folder") String folder,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr) {
try {
AbstractManager.MyResourceId resource = fileManager.getId(folder, studyStr, sessionId);
QueryResult result = catalogManager.getAllFilesInFolder(resource.getResourceId(), queryOptions, sessionId);
return createOkResponse(result);
} catch (Exception e) {
return createErrorResponse(e);
}
}
@Deprecated
@GET
@Path("/{file}/index")
@ApiOperation(value = "Index variant files [DEPRECATED]", position = 14, notes = "Moved to analysis/[variant|alignment]/{file}/index",
hidden = true, response = QueryResponse.class)
public Response index(@ApiParam("Comma separated list of file ids (files or directories)") @PathParam(value = "file") String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
// Study id is not ingested by the analysis index command line. No longer needed.
// @ApiParam("Study id") @QueryParam("studyId") String studyId,
@ApiParam("Output directory id") @QueryParam("outDir") String outDirStr,
@ApiParam("Boolean indicating that only the transform step will be run") @DefaultValue("false")
@QueryParam("transform") boolean transform,
@ApiParam("Boolean indicating that only the load step will be run") @DefaultValue("false")
@QueryParam("load") boolean load,
@ApiParam("Comma separated list of fields to be include in the index")
@QueryParam("includeExtraFields") String includeExtraFields,
@ApiParam("Type of aggregated VCF file: none, basic, EVS or ExAC") @DefaultValue("none")
@QueryParam("aggregated") String aggregated,
@ApiParam("Calculate indexed variants statistics after the load step") @DefaultValue("false")
@QueryParam("calculateStats") boolean calculateStats,
@ApiParam("Annotate indexed variants after the load step") @DefaultValue("false")
@QueryParam("annotate") boolean annotate,
@ApiParam("Overwrite annotations already present in variants") @DefaultValue("false")
@QueryParam("overwrite") boolean overwriteAnnotations) {
Map<String, String> params = new LinkedHashMap<>();
// addParamIfNotNull(params, "studyId", studyId);
addParamIfNotNull(params, "outdir", outDirStr);
addParamIfTrue(params, "transform", transform);
addParamIfTrue(params, "load", load);
addParamIfNotNull(params, EXTRA_GENOTYPE_FIELDS.key(), includeExtraFields);
addParamIfNotNull(params, AGGREGATED_TYPE.key(), aggregated);
addParamIfTrue(params, CALCULATE_STATS.key(), calculateStats);
addParamIfTrue(params, ANNOTATE.key(), annotate);
addParamIfTrue(params, VariantAnnotationManager.OVERWRITE_ANNOTATIONS, overwriteAnnotations);
Set<String> knownParams = new HashSet<>();
knownParams.add("outDir");
knownParams.add("transform");
knownParams.add("load");
knownParams.add("includeExtraFields");
knownParams.add("aggregated");
knownParams.add("calculateStats");
knownParams.add("annotate");
knownParams.add("overwrite");
knownParams.add("sid");
knownParams.add("include");
knownParams.add("exclude");
// Add other params
query.forEach((key, value) -> {
if (!knownParams.contains(key)) {
if (value != null) {
params.put(key, value.toString());
}
}
});
logger.info("ObjectMap: {}", params);
try {
AbstractManager.MyResourceIds resource = fileManager.getIds(fileIdStr, studyStr, sessionId);
QueryResult queryResult = fileManager.index(StringUtils.join(resource.getResourceIds(), ","),
Long.toString(resource.getStudyId()), "VCF", params, sessionId);
return createOkResponse(queryResult);
} catch(Exception e) {
return createErrorResponse(e);
}
// AnalysisFileIndexer analysisFileIndexer = new AnalysisFileIndexer(catalogManager);
//
// try {
// long outDirId = catalogManager.getFileId(outDirStr, sessionId);
// long fileId = catalogManager.getFileId(fileIdStr, sessionId);
// if(outDirId < 0) {
// outDirId = catalogManager.getFileParent(fileId, null, sessionId).first().getId();
// }
// // TODO: Change it to query
// queryOptions.add(VariantStorageEngine.Options.CALCULATE_STATS.key(), calculateStats);
// queryOptions.add(VariantStorageEngine.Options.ANNOTATE.key(), annotate);
// QueryResult<Job> queryResult = analysisFileIndexer.index(fileId, outDirId, sessionId, new QueryOptions(queryOptions));
// return createOkResponse(queryResult);
// } catch (Exception e) {
// return createErrorResponse(e);
// }
}
@GET
@Path("/{folder}/tree")
@ApiOperation(value = "Obtain a tree view of the files and folders within a folder", position = 15, response = FileTree[].class)
@ApiImplicitParams({
@ApiImplicitParam(name = "include", value = "Fields included in the response, whole JSON path must be provided", example = "name,attributes", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "exclude", value = "Fields excluded in the response, whole JSON path must be provided", example = "id,status", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "limit", value = "[TO BE IMPLEMENTED] Number of results to be returned in the queries", dataType = "integer", paramType = "query"),
})
public Response treeView(@ApiParam(value = "Folder id or path. Paths must be separated by : instead of /") @DefaultValue(":")
@PathParam ("folder") String folderId,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "Maximum depth to get files from") @DefaultValue("5") @QueryParam("maxDepth") int maxDepth) {
try {
query.remove("maxDepth");
QueryResult result = fileManager
.getTree(folderId.replace(":", "/"), studyStr, query, queryOptions, maxDepth, sessionId);
return createOkResponse(result);
} catch (Exception e) {
return createErrorResponse(e);
}
}
@Deprecated
@GET
@Path("/{file}/fetch")
@ApiOperation(value = "File fetch [DEPRECATED]", notes = "DEPRECATED. Use .../files/{fileId}/[variants|alignments] or "
+ ".../studies/{studyId}/[variants|alignments] instead", hidden = true, position = 15)
public Response fetch(@PathParam(value = "file") @DefaultValue("") String fileIds,
@ApiParam(value = "region", allowMultiple = true, required = true) @DefaultValue("") @QueryParam("region") String region,
@ApiParam(value = "view_as_pairs", required = false) @DefaultValue("false") @QueryParam("view_as_pairs") boolean view_as_pairs,
@ApiParam(value = "include_coverage", required = false) @DefaultValue("true") @QueryParam("include_coverage") boolean include_coverage,
@ApiParam(value = "process_differences", required = false) @DefaultValue("true") @QueryParam("process_differences") boolean process_differences,
@ApiParam(value = "histogram", required = false) @DefaultValue("false") @QueryParam("histogram") boolean histogram,
@ApiParam(value = "GroupBy: [ct, gene, ensemblGene]", required = false) @DefaultValue("") @QueryParam("groupBy") String groupBy,
@ApiParam(value = "variantSource", required = false) @DefaultValue("false") @QueryParam("variantSource") boolean variantSource,
@ApiParam(value = "interval", required = false) @DefaultValue("2000") @QueryParam("interval") int interval) {
List<Region> regions = new LinkedList<>();
String[] splitFileId = fileIds.split(",");
List<Object> results = new LinkedList<>();
for (String r : region.split(",")) {
regions.add(new Region(r));
}
for (String fileId : splitFileId) {
long fileIdNum;
File file;
URI fileUri;
try {
fileIdNum = catalogManager.getFileId(fileId, null, sessionId);
QueryResult<File> queryResult = catalogManager.getFile(fileIdNum, sessionId);
file = queryResult.getResult().get(0);
fileUri = catalogManager.getFileUri(file);
} catch (CatalogException e) {
e.printStackTrace();
return createErrorResponse(e);
}
// if (!file.getType().equals(File.Type.INDEX)) {
if (file.getIndex() == null || !file.getIndex().getStatus().getName().equals(FileIndex.IndexStatus.READY)) {
return createErrorResponse("", "File {id:" + file.getId() + " name:'" + file.getName() + "'} " +
" is not an indexed file.");
}
// List<Index> indices = file.getIndices();
// Index index = null;
// for (Index i : indices) {
// if (i.getStorageEngine().equals(backend)) {
// index = i;
// }
// }
ObjectMap indexAttributes = new ObjectMap(file.getIndex().getAttributes());
DataStore dataStore = null;
try {
dataStore = StorageOperation.getDataStore(catalogManager, catalogManager.getStudyIdByFileId(file.getId()),
file.getBioformat(), sessionId);
} catch (CatalogException e) {
e.printStackTrace();
return createErrorResponse(e);
}
String storageEngine = dataStore.getStorageEngine();
String dbName = dataStore.getDbName();
// QueryResult result;
QueryResult result;
switch (file.getBioformat()) {
case ALIGNMENT: {
//TODO: getChunkSize from file.index.attributes? use to be 200
int chunkSize = indexAttributes.getInt("coverageChunkSize", 200);
QueryOptions queryOptions = new QueryOptions();
queryOptions.put(AlignmentDBAdaptor.QO_FILE_ID, Long.toString(fileIdNum));
queryOptions.put(AlignmentDBAdaptor.QO_BAM_PATH, fileUri.getPath()); //TODO: Make uri-compatible
queryOptions.put(AlignmentDBAdaptor.QO_VIEW_AS_PAIRS, view_as_pairs);
queryOptions.put(AlignmentDBAdaptor.QO_INCLUDE_COVERAGE, include_coverage);
queryOptions.put(AlignmentDBAdaptor.QO_PROCESS_DIFFERENCES, process_differences);
queryOptions.put(AlignmentDBAdaptor.QO_INTERVAL_SIZE, interval);
queryOptions.put(AlignmentDBAdaptor.QO_HISTOGRAM, histogram);
queryOptions.put(AlignmentDBAdaptor.QO_COVERAGE_CHUNK_SIZE, chunkSize);
if (indexAttributes.containsKey("baiFileId")) {
File baiFile = null;
try {
baiFile = catalogManager.getFile(indexAttributes.getInt("baiFileId"), sessionId).getResult().get(0);
URI baiUri = catalogManager.getFileUri(baiFile);
queryOptions.put(AlignmentDBAdaptor.QO_BAI_PATH, baiUri.getPath()); //TODO: Make uri-compatible
} catch (CatalogException e) {
e.printStackTrace();
logger.error("Can't obtain bai file for file " + fileIdNum, e);
}
}
AlignmentDBAdaptor dbAdaptor;
try {
AlignmentStorageEngine alignmentStorageManager = storageEngineFactory.getAlignmentStorageEngine(storageEngine);
dbAdaptor = alignmentStorageManager.getDBAdaptor(dbName);
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | StorageEngineException e) {
return createErrorResponse(e);
}
// QueryResult alignmentsByRegion;
QueryResult alignmentsByRegion;
if (histogram) {
if (regions.size() != 1) {
return createErrorResponse("", "Histogram fetch only accepts one region.");
}
alignmentsByRegion = dbAdaptor.getAllIntervalFrequencies(regions.get(0), new QueryOptions(queryOptions));
} else {
alignmentsByRegion = dbAdaptor.getAllAlignmentsByRegion(regions, new QueryOptions(queryOptions));
}
result = alignmentsByRegion;
break;
}
case VARIANT: {
String warningMsg = null;
Query query = VariantStorageManager.getVariantQuery(queryOptions);
query.put(VariantDBAdaptor.VariantQueryParams.REGION.key(), region);
// for (Map.Entry<String, List<String>> entry : params.entrySet()) {
// List<String> values = entry.getValue();
// String csv = values.get(0);
// for (int i = 1; i < values.size(); i++) {
// csv += "," + values.get(i);
// }
// queryOptions.add(entry.getKey(), csv);
// }
// queryOptions.put("files", Arrays.asList(Integer.toString(fileIdNum)));
query.put(VariantDBAdaptor.VariantQueryParams.FILES.key(), fileIdNum);
if (params.containsKey("fileId")) {
warningMsg = "Do not use param \"fileI\". Use \"" + VariantDBAdaptor.VariantQueryParams.RETURNED_FILES.key() + "\" instead";
if (params.get("fileId").get(0).isEmpty()) {
query.put(VariantDBAdaptor.VariantQueryParams.RETURNED_FILES.key(), fileId);
} else {
List<String> files = params.get("fileId");
query.put(VariantDBAdaptor.VariantQueryParams.RETURNED_FILES.key(), files);
}
}
VariantDBAdaptor dbAdaptor;
try {
dbAdaptor = storageEngineFactory.getVariantStorageEngine(storageEngine).getDBAdaptor(dbName);
// dbAdaptor = new CatalogVariantDBAdaptor(catalogManager, dbAdaptor);
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | StorageEngineException e) {
return createErrorResponse(e);
}
// QueryResult queryResult;
QueryResult queryResult;
if (histogram) {
queryOptions.put("interval", interval);
queryResult = dbAdaptor.get(new Query(query), new QueryOptions(queryOptions));
// } else if (variantSource) {
// queryOptions.put("fileId", Integer.toString(fileIdNum));
// queryResult = dbAdaptor.getVariantSourceDBAdaptor().getAllSources(queryOptions);
} else if (!groupBy.isEmpty()) {
queryResult = dbAdaptor.groupBy(new Query(query), groupBy, new QueryOptions(queryOptions));
} else {
//With merge = true, will return only one result.
// queryOptions.put("merge", true);
// queryResult = dbAdaptor.getAllVariantsByRegionList(regions, queryOptions).get(0);
queryResult = dbAdaptor.get(new Query(query), new QueryOptions(queryOptions));
}
result = queryResult;
if (warningMsg != null) {
result.setWarningMsg(result.getWarningMsg() == null ? warningMsg : (result.getWarningMsg() + warningMsg));
}
break;
}
default:
return createErrorResponse("", "Unknown bioformat '" + file.getBioformat() + '\'');
}
result.setId(Long.toString(fileIdNum));
System.out.println("result = " + result);
results.add(result);
}
System.out.println("results = " + results);
return createOkResponse(results);
}
@Deprecated
@GET
@Path("/{file}/variants")
@ApiOperation(value = "Fetch variants from a VCF/gVCF file [DEPRECATED]", position = 15,
notes = "Moved to analysis/variants/query", hidden = true, response = QueryResponse.class)
@ApiImplicitParams({
@ApiImplicitParam(name = "include", value = "Fields included in the response, whole JSON path must be provided",
example = "name,attributes", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "exclude", value = "Fields excluded in the response, whole JSON path must be provided", example = "id,status", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "limit", value = "Number of results to be returned in the queries", dataType = "integer", paramType = "query"),
@ApiImplicitParam(name = "skip", value = "Number of results to skip in the queries", dataType = "integer", paramType = "query"),
// @ApiImplicitParam(name = "count", value = "Total number of results", dataType = "boolean", paramType = "query")
})
public Response getVariants(@ApiParam(value = "", required = true) @PathParam("file") String fileIdCsv,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "List of variant ids") @QueryParam("ids") String ids,
@ApiParam(value = "List of regions: {chr}:{start}-{end}") @QueryParam("region") String region,
@ApiParam(value = "List of chromosomes") @QueryParam("chromosome") String chromosome,
@ApiParam(value = "List of genes") @QueryParam("gene") String gene,
@ApiParam(value = "Variant type: [SNV, MNV, INDEL, SV, CNV]") @QueryParam("type") String type,
@ApiParam(value = "Reference allele") @QueryParam("reference") String reference,
@ApiParam(value = "Main alternate allele") @QueryParam("alternate") String alternate,
// @ApiParam(value = "") @QueryParam("studies") String studies,
@ApiParam(value = "List of studies to be returned") @QueryParam("returnedStudies") String returnedStudies,
@ApiParam(value = "List of samples to be returned") @QueryParam("returnedSamples") String returnedSamples,
@ApiParam(value = "List of files to be returned.") @QueryParam("returnedFiles") String returnedFiles,
@ApiParam(value = "Variants in specific files") @QueryParam("files") String files,
@ApiParam(value = VariantDBAdaptor.FILTER_DESCR) @QueryParam("filter") String filter,
@ApiParam(value = "Minor Allele Frequency: [{study:}]{cohort}[<|>|<=|>=]{number}") @QueryParam("maf") String maf,
@ApiParam(value = "Minor Genotype Frequency: [{study:}]{cohort}[<|>|<=|>=]{number}") @QueryParam("mgf") String mgf,
@ApiParam(value = "Number of missing alleles: [{study:}]{cohort}[<|>|<=|>=]{number}") @QueryParam("missingAlleles") String missingAlleles,
@ApiParam(value = "Number of missing genotypes: [{study:}]{cohort}[<|>|<=|>=]{number}") @QueryParam("missingGenotypes") String missingGenotypes,
@ApiParam(value = "Specify if the variant annotation must exists.") @QueryParam("annotationExists") boolean annotationExists,
@ApiParam(value = "Samples with a specific genotype: {samp_1}:{gt_1}(,{gt_n})*(;{samp_n}:{gt_1}(,{gt_n})*)* e.g. HG0097:0/0;HG0098:0/1,1/1") @QueryParam("genotype") String genotype,
@ApiParam(value = VariantDBAdaptor.SAMPLES_DESCR) @QueryParam("samples") String samples,
@ApiParam(value = "Consequence type SO term list. e.g. missense_variant,stop_lost or SO:0001583,SO:0001578") @QueryParam("annot-ct") String annot_ct,
@ApiParam(value = "XRef") @QueryParam("annot-xref") String annot_xref,
@ApiParam(value = "Biotype") @QueryParam("annot-biotype") String annot_biotype,
@ApiParam(value = "Polyphen, protein substitution score. [<|>|<=|>=]{number} or [~=|=|]{description} e.g. <=0.9 , =benign") @QueryParam("polyphen") String polyphen,
@ApiParam(value = "Sift, protein substitution score. [<|>|<=|>=]{number} or [~=|=|]{description} e.g. >0.1 , ~=tolerant") @QueryParam("sift") String sift,
// @ApiParam(value = "") @QueryParam("protein_substitution") String protein_substitution,
@ApiParam(value = "Conservation score: {conservation_score}[<|>|<=|>=]{number} e.g. phastCons>0.5,phylop<0.1,gerp>0.1") @QueryParam("conservation") String conservation,
@ApiParam(value = "Population minor allele frequency: {study}:{population}[<|>|<=|>=]{number}") @QueryParam("annot-population-maf") String annotPopulationMaf,
@ApiParam(value = "Alternate Population Frequency: {study}:{population}[<|>|<=|>=]{number}") @QueryParam("alternate_frequency") String alternate_frequency,
@ApiParam(value = "Reference Population Frequency: {study}:{population}[<|>|<=|>=]{number}") @QueryParam("reference_frequency") String reference_frequency,
@ApiParam(value = "List of transcript annotation flags. e.g. CCDS, basic, cds_end_NF, mRNA_end_NF, cds_start_NF, mRNA_start_NF, seleno") @QueryParam("annot-transcription-flags") String transcriptionFlags,
@ApiParam(value = "List of gene trait association id. e.g. \"umls:C0007222\" , \"OMIM:269600\"") @QueryParam("annot-gene-trait-id") String geneTraitId,
@ApiParam(value = "List of gene trait association names. e.g. \"Cardiovascular Diseases\"") @QueryParam("annot-gene-trait-name") String geneTraitName,
@ApiParam(value = "List of HPO terms. e.g. \"HP:0000545\"") @QueryParam("annot-hpo") String hpo,
@ApiParam(value = "List of GO (Genome Ontology) terms. e.g. \"GO:0002020\"") @QueryParam("annot-go") String go,
@ApiParam(value = "List of tissues of interest. e.g. \"tongue\"") @QueryParam("annot-expression") String expression,
@ApiParam(value = "List of protein variant annotation keywords") @QueryParam("annot-protein-keywords") String proteinKeyword,
@ApiParam(value = "List of drug names") @QueryParam("annot-drug") String drug,
@ApiParam(value = "Functional score: {functional_score}[<|>|<=|>=]{number} e.g. cadd_scaled>5.2 , cadd_raw<=0.3") @QueryParam("annot-functional-score") String functional,
@ApiParam(value = "Returned genotype for unknown genotypes. Common values: [0/0, 0|0, ./.]") @QueryParam("unknownGenotype") String unknownGenotype,
// @ApiParam(value = "Limit the number of returned variants. Max value: " + VariantFetcher.LIMIT_MAX) @DefaultValue(""+VariantFetcher.LIMIT_DEFAULT) @QueryParam("limit") int limit,
// @ApiParam(value = "Skip some number of variants.") @QueryParam("skip") int skip,
@ApiParam(value = "Returns the samples metadata group by study. Sample names will appear in the same order as their corresponding genotypes.", required = false) @QueryParam("samplesMetadata") boolean samplesMetadata,
@ApiParam(value = "Count results", required = false) @QueryParam("count") boolean count,
@ApiParam(value = "Sort the results", required = false) @QueryParam("sort") boolean sort,
@ApiParam(value = "Group variants by: [ct, gene, ensemblGene]", required = false) @DefaultValue("") @QueryParam("groupBy") String groupBy,
@ApiParam(value = "Calculate histogram. Requires one region.", required = false) @DefaultValue("false") @QueryParam("histogram") boolean histogram,
@ApiParam(value = "Histogram interval size", required = false) @DefaultValue("2000") @QueryParam("interval") int interval,
@ApiParam(value = "Merge results", required = false) @DefaultValue("false") @QueryParam("merge") boolean merge) {
List<QueryResult> queryResults = new LinkedList<>();
try {
AbstractManager.MyResourceIds resource = fileManager.getIds(fileIdCsv, studyStr, sessionId);
// String[] splitFileId = fileIdCsv.split(",");
for (long fileId : resource.getResourceIds()) {
QueryResult queryResult;
// Get all query options
QueryOptions queryOptions = new QueryOptions(uriInfo.getQueryParameters(), true);
Query query = VariantStorageManager.getVariantQuery(queryOptions);
query.put(VariantDBAdaptor.VariantQueryParams.FILES.key(), fileId);
if (count) {
queryResult = variantManager.count(query, sessionId);
} else if (histogram) {
queryResult = variantManager.getFrequency(query, interval, sessionId);
} else if (StringUtils.isNotEmpty(groupBy)) {
queryResult = variantManager.groupBy(groupBy, query, queryOptions, sessionId);
} else {
queryResult = variantManager.get(query, queryOptions, sessionId);
}
queryResults.add(queryResult);
}
} catch (Exception e) {
return createErrorResponse(e);
}
return createOkResponse(queryResults);
}
private ObjectMap getResumeFileJSON(java.nio.file.Path folderPath) throws IOException {
ObjectMap objectMap = new ObjectMap();
if (Files.exists(folderPath)) {
DirectoryStream<java.nio.file.Path> folderStream = Files.newDirectoryStream(folderPath, "*_partial");
for (java.nio.file.Path partPath : folderStream) {
String[] nameSplit = partPath.getFileName().toString().split("_");
ObjectMap chunkInfo = new ObjectMap();
chunkInfo.put("size", Integer.parseInt(nameSplit[1]));
objectMap.put(nameSplit[0], chunkInfo);
}
}
return objectMap;
}
private List<java.nio.file.Path> getSortedChunkList(java.nio.file.Path folderPath) throws IOException {
List<java.nio.file.Path> files = new ArrayList<>();
DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(folderPath, "*_partial");
for (java.nio.file.Path p : stream) {
logger.info("adding to ArrayList: " + p.getFileName());
files.add(p);
}
logger.info("----ordered files length: " + files.size());
Collections.sort(files, new Comparator<java.nio.file.Path>() {
public int compare(java.nio.file.Path o1, java.nio.file.Path o2) {
int id_o1 = Integer.parseInt(o1.getFileName().toString().split("_")[0]);
int id_o2 = Integer.parseInt(o2.getFileName().toString().split("_")[0]);
return id_o1 - id_o2;
}
});
return files;
}
@GET
@Path("/{file}/update")
@ApiOperation(value = "Update fields of a file [WARNING]", position = 16, response = File.class,
notes = "WARNING: the usage of this web service is discouraged, please use the POST version instead. Be aware that this is web "
+ "service is not tested and this can be deprecated in a future version.")
public Response update(@ApiParam(value = "File id") @PathParam(value = "file") String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "File name", required = false) @QueryParam("name") String name,
@ApiParam(value = "Format of the file (VCF, BCF, GVCF, SAM, BAM, BAI...UNKNOWN)", required = false) @QueryParam("format") String format,
@ApiParam(value = "Bioformat of the file (VARIANT, ALIGNMENT, SEQUENCE, PEDIGREE...NONE)", required = false) @QueryParam("bioformat") String bioformat,
@ApiParam(value = "Description of the file", required = false) @QueryParam("description") String description,
@ApiParam(value = "Attributes", required = false) @QueryParam("attributes") String attributes,
@ApiParam(value = "Stats", required = false) @QueryParam("stats") String stats,
@ApiParam(value = "Sample ids", required = false) @QueryParam("sampleIds") String sampleIds,
@ApiParam(value = "(DEPRECATED) Job id", hidden = true) @QueryParam("jobId") String jobIdOld,
@ApiParam(value = "Job id", required = false) @QueryParam("job.id") String jobId) {
try {
/*ObjectMap parameters = new ObjectMap();
QueryOptions qOptions = new QueryOptions();
parseQueryParams(params, CatalogFileDBAdaptor.QueryParams::getParam, parameters, qOptions);*/
ObjectMap params = new ObjectMap(query);
// TODO: jobId is deprecated. Remember to remove this if after next release
if (params.containsKey("jobId") && !params.containsKey(FileDBAdaptor.QueryParams.JOB_ID.key())) {
params.put(FileDBAdaptor.QueryParams.JOB_ID.key(), params.get("jobId"));
params.remove("jobId");
}
params.remove(FileDBAdaptor.QueryParams.STUDY.key());
// params.putIfNotEmpty(FileDBAdaptor.QueryParams.NAME.key(), name);
// params.putIfNotEmpty(FileDBAdaptor.QueryParams.FORMAT.key(), format);
// params.putIfNotEmpty(FileDBAdaptor.QueryParams.BIOFORMAT.key(), bioformat);
// params.putIfNotEmpty(FileDBAdaptor.QueryParams.DESCRIPTION.key(), description);
// params.putIfNotEmpty(FileDBAdaptor.QueryParams.ATTRIBUTES.key(), attributes);
// params.putIfNotEmpty(FileDBAdaptor.QueryParams.STATS.key(), stats);
// params.putIfNotEmpty(FileDBAdaptor.QueryParams.SAMPLE_IDS.key(), sampleIds);
// params.putIfNotEmpty(FileDBAdaptor.QueryParams.JOB_ID.key(), jobIdOld);
// params.putIfNotEmpty(FileDBAdaptor.QueryParams.JOB_ID.key(), jobId);
AbstractManager.MyResourceId resource = fileManager.getId(fileIdStr, studyStr, sessionId);
QueryResult queryResult = fileManager.update(resource.getResourceId(), params, queryOptions, sessionId);
queryResult.setId("Update file");
return createOkResponse(queryResult);
} catch (Exception e) {
return createErrorResponse(e);
}
}
public static class UpdateFile {
public String name;
public File.Format format;
public File.Bioformat bioformat;
// public String path;
// public String ownerId;
// public String creationDate;
// public String modificationDate;
public String description;
// public Long size;
// public int experimentId;
public String sampleIds;
public Long jobId;
public Map<String, Object> stats;
public Map<String, Object> attributes;
}
@POST
@Path("/{file}/update")
@ApiOperation(value = "Modify file", position = 16, response = File.class)
public Response updatePOST(@ApiParam(value = "File id") @PathParam(value = "file") String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(name = "params", value = "Parameters to modify", required = true) ObjectMap params) {
try {
AbstractManager.MyResourceId resource = fileManager.getId(fileIdStr, studyStr, sessionId);
ObjectMap map = new ObjectMap(jsonObjectMapper.writeValueAsString(params));
// TODO: jobId is deprecated. Remember to remove this if after next release
if (map.get("jobId") != null) {
map.put(FileDBAdaptor.QueryParams.JOB_ID.key(), map.get("jobId"));
map.remove("jobId");
}
QueryResult<File> queryResult = fileManager.update(resource.getResourceId(), map, queryOptions, sessionId);
queryResult.setId("Update file");
return createOkResponse(queryResult);
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/link")
@ApiOperation(value = "Link an external file into catalog.", hidden = true, position = 19, response = QueryResponse.class)
public Response link(@ApiParam(value = "Uri of the file", required = true) @QueryParam("uri") String uriStr,
@ApiParam(value = "(DEPRECATED) Use study instead") @QueryParam("studyId") String studyIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias") @QueryParam("study") String studyStr,
@ApiParam(value = "Path where the external file will be allocated in catalog", required = true) @QueryParam("path") String path,
@ApiParam(value = "Description") @QueryParam("description") String description,
@ApiParam(value = "Create the parent directories if they do not exist") @DefaultValue("false") @QueryParam("parents") boolean parents,
@ApiParam(value = "Size of the folder/file") @QueryParam("size") long size,
@ApiParam(value = "Checksum of something") @QueryParam("checksum") String checksum) {
try {
if (StringUtils.isNotEmpty(studyIdStr)) {
studyStr = studyIdStr;
}
logger.debug("study: {}", studyStr);
path = path.replace(":", "/");
ObjectMap objectMap = new ObjectMap()
.append("parents", parents)
.append("description", description);
List<String> uriList = Arrays.asList(uriStr.split(","));
List<QueryResult<File>> queryResultList = new ArrayList<>();
logger.info("path: {}", path);
if (uriList.size() == 1) {
// If it is just one uri to be linked, it will return an error response if there is some kind of error.
URI myUri = UriUtils.createUri(uriList.get(0));
queryResultList.add(catalogManager.link(myUri, path, studyStr, objectMap, sessionId));
} else {
for (String uri : uriList) {
logger.info("uri: {}", uri);
try {
URI myUri = UriUtils.createUri(uri);
queryResultList.add(catalogManager.link(myUri, path, studyStr, objectMap, sessionId));
} catch (URISyntaxException | CatalogException | IOException e) {
queryResultList.add(new QueryResult<>("Link file", -1, 0, 0, "", e.getMessage(), Collections.emptyList()));
}
}
}
return createOkResponse(queryResultList);
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/unlink")
@ApiOperation(value = "Unlink an external file from catalog.", hidden = true, position = 20, response = QueryResponse.class)
public Response unlink(@ApiParam(value = "File id", required = true) @QueryParam("fileId") String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr) throws CatalogException {
try {
QueryResult<File> queryResult = catalogManager.getFileManager().unlink(fileIdStr, studyStr, sessionId);
return createOkResponse(new QueryResult<>("unlink", 0, 1, 1, null, null, queryResult.getResult()));
} catch (Exception e) {
return createErrorResponse(e);
}
}
@Deprecated
@GET
@Path("/{fileId}/relink")
@ApiOperation(value = "Change file location. Provided file must be either STAGE or be an external file. [DEPRECATED]", hidden = true,
position = 21)
public Response relink(@ApiParam(value = "File Id") @PathParam("fileId") @DefaultValue("") String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "New URI" ,required = true) @QueryParam("uri") String uriStr,
@ApiParam(value = "Do calculate checksum for new files", required = false) @DefaultValue("false")
@QueryParam("calculateChecksum") boolean calculateChecksum ) {
try {
URI uri = UriUtils.createUri(uriStr);
CatalogIOManager ioManager = catalogManager.getCatalogIOManagerFactory().get(uri);
if (!ioManager.exists(uri)) {
throw new CatalogIOException("File " + uri + " does not exist");
}
AbstractManager.MyResourceId resource = fileManager.getId(fileIdStr, studyStr, sessionId);
File file = catalogManager.getFile(resource.getResourceId(), sessionId).first();
new CatalogFileUtils(catalogManager).link(file, calculateChecksum, uri, false, true, sessionId);
file = catalogManager.getFile(file.getId(), queryOptions, sessionId).first();
file = FileMetadataReader.get(catalogManager).setMetadataInformation(file, null, new QueryOptions(queryOptions), sessionId,
false);
return createOkResponse(new QueryResult<>("relink", 0, 1, 1, null, null, Collections.singletonList(file)));
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/{file}/refresh")
@ApiOperation(value = "Refresh metadata from the selected file or folder. Return updated files.", position = 22,
response = QueryResponse.class)
public Response refresh(@ApiParam(value = "File id") @PathParam(value = "file") String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr) {
try {
AbstractManager.MyResourceId resource = fileManager.getId(fileIdStr, studyStr, sessionId);
File file = catalogManager.getFile(resource.getResourceId(), sessionId).first();
List<File> files;
CatalogFileUtils catalogFileUtils = new CatalogFileUtils(catalogManager);
FileMetadataReader fileMetadataReader = FileMetadataReader.get(catalogManager);
if (file.getType() == File.Type.FILE) {
File file1 = catalogFileUtils.checkFile(file, false, sessionId);
file1 = fileMetadataReader.setMetadataInformation(file1, null, new QueryOptions(queryOptions), sessionId, false);
if (file == file1) { //If the file is the same, it was not modified. Only return modified files.
files = Collections.emptyList();
} else {
files = Collections.singletonList(file);
}
} else {
List<File> result = catalogManager.getAllFilesInFolder(file.getId(), null, sessionId).getResult();
files = new ArrayList<>(result.size());
for (File f : result) {
File file1 = fileMetadataReader.setMetadataInformation(f, null, new QueryOptions(queryOptions), sessionId, false);
if (f != file1) { //Add only modified files.
files.add(file1);
}
}
}
return createOkResponse(new QueryResult<>("refresh", 0, files.size(), files.size(), null, null, files));
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/{file}/delete")
@ApiOperation(value = "Delete file", position = 23, response = QueryResponse.class)
public Response deleteGET(@ApiParam(value = "File id") @PathParam(value = "file") String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "Delete files and folders from disk (only applicable for linked files/folders)",
required = false) @DefaultValue("false") @QueryParam("deleteExternal") boolean deleteExternal,
@ApiParam(value="Skip trash and delete the files/folders from disk directly (CANNOT BE RECOVERED)",
required = false) @DefaultValue("false") @QueryParam("skipTrash") boolean skipTrash) {
try {
// QueryOptions qOptions = new QueryOptions(queryOptions)
ObjectMap params = new ObjectMap()
.append(FileManager.DELETE_EXTERNAL_FILES, deleteExternal)
.append(FileManager.SKIP_TRASH, skipTrash);
List<QueryResult<File>> result = fileManager.delete(fileIdStr, studyStr, params, sessionId);
return createOkResponse(result);
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/groupBy")
@ApiOperation(value = "Group files by several fields", position = 24, response = QueryResponse.class)
public Response groupBy(@ApiParam(value = "Comma separated list of fields by which to group by.", required = true) @DefaultValue("")
@QueryParam("fields") String fields,
@ApiParam(value = "(DEPRECATED) Use study instead", hidden = true) @DefaultValue("") @QueryParam("studyId")
String studyIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "Comma separated list of ids.", required = false) @DefaultValue("") @QueryParam("id")
String ids,
@ApiParam(value = "Comma separated list of names.", required = false) @DefaultValue("") @QueryParam("name")
String names,
@ApiParam(value = "path", required = false) @DefaultValue("") @QueryParam("path") String path,
@ApiParam(value = "Comma separated Type values.", required = false) @DefaultValue("") @QueryParam("type")
String type,
@ApiParam(value = "Comma separated Bioformat values.", required = false) @DefaultValue("")
@QueryParam("bioformat") String bioformat,
@ApiParam(value = "Comma separated Format values.", required = false) @DefaultValue("") @QueryParam("format")
String formats,
@ApiParam(value = "status", required = false) @DefaultValue("") @QueryParam("status") String status,
@ApiParam(value = "directory", required = false) @DefaultValue("") @QueryParam("directory") String directory,
@ApiParam(value = "creationDate", required = false) @DefaultValue("") @QueryParam("creationDate")
String creationDate,
@ApiParam(value = "modificationDate", required = false) @DefaultValue("") @QueryParam("modificationDate")
String modificationDate,
@ApiParam(value = "description", required = false) @DefaultValue("") @QueryParam("description")
String description,
@ApiParam(value = "size", required = false) @DefaultValue("") @QueryParam("size") Long size,
@ApiParam(value = "Comma separated sampleIds", required = false) @DefaultValue("") @QueryParam("sampleIds")
String sampleIds,
@ApiParam(value = "(DEPRECATED) Job id", hidden = true) @QueryParam("jobId") String jobIdOld,
@ApiParam(value = "Job id", required = false) @QueryParam("job.id") String jobId,
@ApiParam(value = "attributes", required = false) @DefaultValue("") @QueryParam("attributes") String attributes,
@ApiParam(value = "numerical attributes", required = false) @DefaultValue("") @QueryParam("nattributes")
String nattributes) {
try {
if (StringUtils.isNotEmpty(studyIdStr)) {
studyStr = studyIdStr;
}
QueryResult result = fileManager.groupBy(studyStr, query, queryOptions, fields, sessionId);
return createOkResponse(result);
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/{files}/acl")
@ApiOperation(value = "Return the acl defined for the file or folder", position = 18, response = QueryResponse.class)
public Response getAcls(@ApiParam(value = "Comma separated list of file ids", required = true) @PathParam("files") String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr) {
try {
return createOkResponse(catalogManager.getAllFileAcls(fileIdStr, studyStr, sessionId));
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/{files}/acl/create")
@ApiOperation(value = "Define a set of permissions for a list of users or groups", hidden = true, position = 19,
response = QueryResponse.class)
public Response createAcl(@ApiParam(value = "Comma separated list of file ids", required = true) @PathParam("files")
String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "Comma separated list of permissions that will be granted to the member list",
required = false) @DefaultValue("") @QueryParam("permissions") String permissions,
@ApiParam(value = "Comma separated list of members. Accepts: '{userId}', '@{groupId}' or '*'",
required = true) @DefaultValue("") @QueryParam("members") String members) {
try {
return createOkResponse(catalogManager.getFileManager().createAcls(fileIdStr, studyStr, members, permissions,
sessionId));
} catch (Exception e) {
return createErrorResponse(e);
}
}
@POST
@Path("/{files}/acl/create")
@ApiOperation(value = "Define a set of permissions for a list of users or groups", response = QueryResponse.class)
public Response createAclPOST(
@ApiParam(value = "Comma separated list of file ids", required = true) @PathParam("files") String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias") @QueryParam("study")
String studyStr,
@ApiParam(value="JSON containing the parameters defined in GET. Mandatory keys: 'members'", required = true)
StudyWSServer.CreateAclCommands params) {
try {
return createOkResponse(catalogManager.getFileManager().createAcls(fileIdStr, studyStr, params.members, params.permissions,
sessionId));
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/{file}/acl/{memberId}/info")
@ApiOperation(value = "Return the permissions granted for the user or group", position = 20, response = QueryResponse.class)
public Response getAcl(@ApiParam(value = "File id", required = true) @PathParam("file") String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "User or group id", required = true) @PathParam("memberId") String memberId) {
try {
return createOkResponse(catalogManager.getFileAcl(fileIdStr, studyStr, memberId, sessionId));
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/{file}/acl/{memberId}/update")
@ApiOperation(value = "Update the permissions granted for the user or group", hidden = true, position = 21,
response = QueryResponse.class)
public Response updateAcl(@ApiParam(value = "File id", required = true) @PathParam("file") String fileIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "User or group id", required = true) @PathParam("memberId") String memberId,
@ApiParam(value = "Comma separated list of permissions to add", required = false)
@QueryParam("add") String addPermissions,
@ApiParam(value = "Comma separated list of permissions to remove", required = false)
@QueryParam("remove") String removePermissions,
@ApiParam(value = "Comma separated list of permissions to set", required = false)
@QueryParam("set") String setPermissions) {
try {
return createOkResponse(catalogManager.getFileManager().updateAcls(fileIdStr, studyStr, memberId, addPermissions,
removePermissions, setPermissions, sessionId));
} catch (Exception e) {
return createErrorResponse(e);
}
}
@POST
@Path("/{file}/acl/{memberId}/update")
@ApiOperation(value = "Update the permissions granted for the user or group", position = 21, response = QueryResponse.class)
public Response updateAclPOST(
@ApiParam(value = "File id", required = true) @PathParam("file") String fileIdStr,
@ApiParam(value = "User or group id", required = true) @PathParam("memberId") String memberId,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias") @QueryParam("study")
String studyStr,
@ApiParam(value="JSON containing one of the keys 'add', 'set' or 'remove'", required = true)
StudyWSServer.MemberAclUpdate params) {
try {
return createOkResponse(catalogManager.getFileManager().updateAcls(fileIdStr, studyStr, memberId, params.add, params.remove,
params.set, sessionId));
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/{files}/acl/{memberIds}/delete")
@ApiOperation(value = "Remove all the permissions granted for the user or group", position = 22,
response = QueryResponse.class)
public Response deleteAcl(@ApiParam(value = "Comma separated list of file ids", required = true) @PathParam("files")
String fileIdsStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "Comma separated list of members", required = true) @PathParam("memberIds") String
members) {
try {
return createOkResponse(catalogManager.getFileManager().removeFileAcls(fileIdsStr, studyStr, members, sessionId));
} catch (Exception e) {
return createErrorResponse(e);
}
}
@GET
@Path("/{folder}/scan")
@ApiOperation(value = "Scans a folder", position = 6)
public Response scan(@ApiParam(value = "Folder id") @PathParam("folder") String folderIdStr,
@ApiParam(value = "Study [[user@]project:]study where study and project can be either the id or alias")
@QueryParam("study") String studyStr,
@ApiParam(value = "calculateChecksum") @QueryParam("calculateChecksum") @DefaultValue("false")
boolean calculateChecksum) {
try {
AbstractManager.MyResourceId resource = fileManager.getId(folderIdStr, studyStr, sessionId);
File directory = catalogManager.getFile(resource.getResourceId(), sessionId).first();
List<File> scan = new FileScanner(catalogManager)
.scan(directory, null, FileScanner.FileScannerPolicy.REPLACE, calculateChecksum, false, sessionId);
return createOkResponse(new QueryResult<>("Scan", 0, scan.size(), scan.size(), "", "", scan));
} catch (Exception e) {
return createErrorResponse(e);
}
}
@Deprecated
public static String convertPath(String path, String sessionId) throws CatalogException {
return convertPath(path, sessionId, catalogManager);
}
// Visible only for testing purposes
@Deprecated
static String convertPath(String path, String sessionId, CatalogManager catalogManager) throws CatalogException {
if (path == null) {
return null;
}
if (path.contains("/") || !path.contains(":")) {
return path;
}
// Path contains :
if (path.startsWith(":")) {
return path.replace(":", "/");
} else {
// Get the user id
String userId = catalogManager.getUserManager().getId(sessionId);
// Get only the first part to check if it corresponds with user@project
int position = path.indexOf(":");
String project = path.substring(0, position);
// Check if it corresponds with a project
long id = catalogManager.getProjectManager().getId(userId, project);
if (id <= 0) {
// Was it a study user@study:filePath/...?
id = catalogManager.getStudyManager().getId(userId, project);
if (id <= 0) {
// Then it must be user@filePath/...
return path.replace(":", "/");
} else {
// It must be user@study:filePath/...
return project + ":" + path.substring(position + 1).replace(":", "/");
}
} else {
// Does it have the study as well? user@project:study:filePath/...
int position2 = path.substring(position + 1).indexOf(":");
if (position2 == -1) {
throw new CatalogException("No file was found in " + path);
} else {
// We should have something like user@project:study
String study = project + path.substring(position).substring(0, position2 + 1);
// Check if the study exists
id = catalogManager.getStudyManager().getId(userId, study);
if (id <= 0) {
// Then it must be user@project:filePath/...
throw new CatalogException("Passing files with this structure user@project:filePath/... is not supported.");
} else {
// The structure seems to be user@project:study:filePath/...
return study + ":" + path.substring(position).substring(position2 + 2).replace(":", "/");
}
}
}
// return path.substring(0, position + 1) + path.substring(position + 1).replace(":", "/");
}
}
@Deprecated
public static List<String> convertPathList(String path, String sessionId) throws CatalogException {
if (path == null) {
return Collections.emptyList();
} else if (path.contains(",")) {
String[] split = path.split(",");
List<String> pathList = new ArrayList<>(split.length);
for (String s : split) {
pathList.add(convertPath(s, sessionId));
}
return pathList;
} else {
return Collections.singletonList(convertPath(path, sessionId));
}
}
}