/* * The MIT License (MIT) * * Copyright (c) 2007-2015 Broad Institute * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.broad.igv.util; import org.apache.log4j.Logger; import org.broad.igv.ga4gh.Ga4ghAPIHelper; import org.broad.igv.ga4gh.GoogleUtils; import org.broad.igv.gs.GSUtils; import htsjdk.tribble.Tribble; import java.awt.*; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.net.URLDecoder; import java.util.HashMap; import java.util.Map; /** * Represents a data file or other resource, which might be local file or remote resource. * * @author jrobinso */ public class ResourceLocator { private static Logger log = Logger.getLogger(ResourceLocator.class); /** * Display name */ String name; /** * The local path or url (http, https, or ftp) for the resource. */ String path; /** * URL to a database server */ String dbURL; /** * Optional path to an associated index file */ String indexPath; /** * /** * Path to an associated density file. This is used primarily for sequence alignments */ String coverage; /** * Optional path to an associated variant->bam mapping file (vcf only) */ String mappingPath; /** * URL to a page with general information about the resource */ String trackInforURL; /** * A URL pattern (UCSC convention) to a specific URL applicable to each feature */ String featureInfoURL; /** * Descriptive text */ String description; /** * The type of resource (generally this refers to the file format) */ String type; /** * A UCSC style track line. Overrides value in file, if any. */ String trackLine; // /** * Color for features or data. Somewhat redundant with trackLine. */ Color color; String sampleId; String username; String password; private HashMap attributes = new HashMap(); /** * Constructor for local files * * @param path */ public ResourceLocator(String path) { this.setPath(path); } /** * Constructor for database resources * * @param dbURL * @param path */ public ResourceLocator(String dbURL, String path) { this.dbURL = dbURL; this.setPath(path); } /** * Determines if the resource actually exists. * * @return true if resource was found. */ public boolean exists() { return ParsingUtils.pathExists(path); } public void setType(String type) { this.type = type; } public String getType() { return type; } /** * Return a string suitable for determining file type based on extension * May or may not be a full, readable path. txt and gz extensions are stripped * * @return */ public String getTypeString() { if (type != null) { return type; } else { String typeString = path.toLowerCase(); if (path.startsWith("http://") || path.startsWith("https://")) { try { URL url = new URL(path); typeString = url.getPath().toLowerCase(); String query = url.getQuery(); if (query != null) { Map<String, String> queryMap = HttpUtils.parseQueryString(query); // If type is set explicitly use it if (queryMap.containsKey("dataformat")) { String format = queryMap.get("dataformat"); if (format.contains("genomespace")) { typeString = GSUtils.parseDataFormatString(format); } else { typeString = format; } } else if (queryMap.containsKey("file")) { typeString = queryMap.get("file"); } } } catch (MalformedURLException e) { log.error("Error interpreting url: " + path, e); typeString = path; } } // Strip .txt, .gz, and .xls extensions. (So foo.cn.gz => a .cn file) if ((typeString.endsWith(".txt") || typeString.endsWith( ".xls") || typeString.endsWith(".gz") || typeString.endsWith(".bgz"))) { typeString = typeString.substring(0, typeString.lastIndexOf(".")).trim(); } return typeString; } } /** * Returns the portion of the contained path before the query string. * If there is no query string, or if the path is not a url, * this will be the same as #getPath() * * @return */ public String getURLPath() { return getPath().split("\\?", 2)[0]; } /** * Returns the portion of the contained path after the query string. * If there is no query string, this will return an empty string * * @return */ public String getURLQueryString() { String[] tmp = getPath().split("\\?", 2); if (tmp.length == 1) { return ""; } return tmp[1]; } public String toString() { return path + (dbURL == null ? "" : " " + dbURL); } public String getPath() { return path; } public String getFileName() { return (new File(path)).getName(); } public String getDBUrl() { return dbURL; } public boolean isLocal() { return dbURL == null && !FileUtils.isRemote(path) && !Ga4ghAPIHelper.RESOURCE_TYPE.equals(type); } public void setTrackInforURL(String trackInforURL) { this.trackInforURL = trackInforURL; } public String getTrackInfoURL() { return trackInforURL; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getTrackName() { if (name == null) { if (path.startsWith("http://") || path.startsWith("https://")) { try { return new File((new URL(URLDecoder.decode(path))).getPath()).getName(); } catch (MalformedURLException e) { return path; } } else { return new File(path).getName(); } } return name; } public void setName(String name) { this.name = name; } public String getName() { return name; } public String getCoverage() { return coverage; } public void setCoverage(String coverage) { this.coverage = coverage; } public Color getColor() { return color; } public void setColor(Color color) { this.color = color; } public String getFeatureInfoURL() { return featureInfoURL; } public void setFeatureInfoURL(String featureInfoURL) { this.featureInfoURL = featureInfoURL; } public void setPath(String path) { if (path != null && path.startsWith("file://")) { this.path = path.substring(7); } else if (path != null && path.startsWith("gs://")) { this.path = GoogleUtils.translateGoogleCloudURL(path); } else { this.path = path; } } public String getTrackLine() { return trackLine; } public void setTrackLine(String trackLine) { this.trackLine = trackLine; } public String getSampleId() { return sampleId; } public void setSampleId(String sampleId) { this.sampleId = sampleId; } public String getIndexPath() { return indexPath; } public void setIndexPath(String indexPath) { this.indexPath = indexPath; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ResourceLocator that = (ResourceLocator) o; if (dbURL != null ? !dbURL.equals(that.dbURL) : that.dbURL != null) return false; if (path != null ? !path.equals(that.path) : that.path != null) return false; return true; } @Override public int hashCode() { int result = path != null ? path.hashCode() : 0; result = 31 * result + (dbURL != null ? dbURL.hashCode() : 0); return result; } public String getBamIndexPath() { if (indexPath != null) return indexPath; if (path.toLowerCase().startsWith("http://") || path.toLowerCase().startsWith("https://")) { // See if bam file is specified by parameter try { URL url = new URL(path); String queryString = url.getQuery(); if (queryString != null) { Map<String, String> parameters = HttpUtils.parseQueryString(queryString); if (parameters.containsKey("index")) { return parameters.get("index"); } else if (parameters.containsKey("file")) { String bamFile = parameters.get("file"); String bamIndexFile = bamFile + ".bai"; String newQueryString = queryString.replace(bamFile, bamIndexFile); return path.replace(queryString, newQueryString); } else { String ip = path.replace(url.getPath(), url.getPath() + ".bai"); return ip; } } } catch (MalformedURLException e) { log.error(e.getMessage(), e); } } return path + ".bai"; } public String getMappingPath() { return mappingPath; } public void setMappingPath(String mappingPath) { this.mappingPath = mappingPath; } /** * Add the {@code indexExtension} to the path in locator, preserving * query string elements if present * * @param locator * @param indexExtension * @return */ public static String appendToPath(ResourceLocator locator, String indexExtension) { String indexFile = locator.getURLPath() + indexExtension; String qs = locator.getURLQueryString(); if (qs != null && qs.length() > 0) { indexFile += "?" + qs; } return indexFile; } /** * @param locator * @return locator.getIndexPath() if not null, otherwise * {@link #appendToPath(ResourceLocator, String)} * where the second argument is .idx or tbi, depending on the resource */ public static String indexFile(ResourceLocator locator) { if (locator.getIndexPath() != null) { return locator.getIndexPath(); } String indexExtension = (locator.getURLPath().toLowerCase().endsWith(".gz") || locator.getPath().toLowerCase().endsWith(".bgz")) ? ".tbi" : Tribble.STANDARD_INDEX_EXTENSION; return appendToPath(locator, indexExtension); } public void setAttribute(String key, Object value) { this.attributes.put(key, value); } public Object getAttribute(String key) { return attributes.get(key); } /** * FOR LOAD FROM SERVER */ public enum AttributeType { DB_URL("serverURL"), PATH("path"), DESCRIPTION("description"), HYPERLINK("hyperlink"), INFOLINK("infolink"), ID("id"), SAMPLE_ID("sampleId"), NAME("name"), URL("url"), RESOURCE_TYPE("resourceType"), TRACK_LINE("trackLine"), COVERAGE("coverage"), MAPPING("mapping"), COLOR("color"), INDEX("index"); private String name; AttributeType(String name) { this.name = name; } public String getText() { return name; } @Override public String toString() { return getText(); } } }