// BridgeDb,
// An abstraction layer for identifier mapping services, both local and online.
// Copyright 2006-2009 BridgeDb developers
//
// 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.bridgedb.file;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bridgedb.BridgeDb;
import org.bridgedb.IDMapper;
import org.bridgedb.IDMapperException;
import org.bridgedb.Xref;
/**
* Class for mapping ID from delimited text file.
* @author gjj
*/
public class IDMapperText extends IDMapperFile
{
static
{
BridgeDb.register ("idmapper-text", new Driver());
}
/** Knows how to instantiate IDMapperText. */
private static final class Driver implements org.bridgedb.Driver
{
/** prevent outside instantiation. */
private Driver() {}
/** {@inheritDoc} */
public IDMapper connect(String location) throws IDMapperException
{
// parse arguments to determine idsep and dssep
// sample: dssep=\t,idsep=;,idsep=,,transitivity=false@file:/localfile.txt
// \t represents tab, \@ represents @
String path = null;
char[] dssep = null;
char[] idsep = null;
boolean transitivity = false;
int idx = location.indexOf("@");
if (idx<=0) {
path = location;
// defaults if no options are provided:
idsep = new char[] { ',' };
dssep = new char[] { '\t' };
} else {
// Is an url always contains :/ ?
if (idx > location.indexOf(":/")) { //@ is part of the path
path = location;
} else {
while (idx>0 && location.charAt(idx-1)=='\\') { //escape \@
idx = location.indexOf(idx+1);
}
if (idx==-1) {
throw new IDMapperException("Wrong link format!");
}
if (idx==location.length()-1) {
throw new IDMapperException("Empty address!");
}
path = location.substring(idx+1);
String config = location.substring(0, idx)+",";
String prefixTran = "transitivity=";
idx = config.indexOf(prefixTran);
String tran = config.substring(idx+prefixTran.length());
if (tran.toLowerCase().startsWith("true")) {
transitivity = true;
} else if (tran.toLowerCase().startsWith("false")) {
transitivity = false;
} else {
throw new IDMapperException(
"transivity can only be true or false");
}
dssep = parseConfig(config, "dssep");
idsep = parseConfig(config, "idsep");
}
}
try
{
return new IDMapperText(new URL(path), dssep, idsep,
transitivity);
}
catch (MalformedURLException ex)
{
throw new IDMapperException(ex);
}
}
/**
* parse the separator list part of the connection string.
* \@ or \t will be unescaped.
* @param config the connection string to parse
* @param head the section to look for, either dssep or idsep
* @return separators
*/
private char[] parseConfig(String config, String head) {
Set<Character> delimiters = new HashSet<Character>();
Pattern p = Pattern.compile(head+"=(.|\\t|\\@),",
Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(config);
while (m.find()) {
String sep = m.group(1);
if (sep.equalsIgnoreCase("\\t")) {
sep = "\t";
} else if (sep.equalsIgnoreCase("\\@")) {
sep = "@";
}
delimiters.add(sep.charAt(0));
}
int nsep = delimiters.size();
if (nsep==0) {
return null;
}
char[] ret = new char[nsep];
int isep = 0;
for (char c : delimiters) {
ret[isep++] = c;
}
return ret;
}
}
private final URL url;
private char[] dataSourceDelimiters;
private char[] idDelimiters;
private boolean transitivity;
/**
* Constructor from the {@link URL} of a tab-delimited text file.
* @param url {@link URL} of the file
* @throws IDMapperException if failed to read file
*/
public IDMapperText(final URL url) throws IDMapperException {
this(url, new char[] {'\t'}); // default is tab delimited
}
/**
* Transitivity is unsupported. No delimiter between data sources.
* @param url url {@link URL} of the file
* @param dataSourceDelimiters delimiters between data sources
* @throws IDMapperException if failed to read file
*/
public IDMapperText(final URL url,
final char[] dataSourceDelimiters) throws IDMapperException {
this(url, dataSourceDelimiters, null);
}
/**
* Transitivity is unsupported.
* @param url url {@link URL} of the file
* @param dataSourceDelimiters delimiters between data sources
* @param idDelimiters delimiters between IDs
* @throws IDMapperException if failed to read file
*/
public IDMapperText(final URL url,
final char[] dataSourceDelimiters,
final char[] idDelimiters) throws IDMapperException {
this(url, dataSourceDelimiters, idDelimiters, false);
}
/**
* Constructor from the {@link URL} of a tab-delimited text file,
* delimiters to separate between different data sources and IDs and
* transitivity support.
* @param url url {@link URL} of the file
* @param dataSourceDelimiters delimiters between data sources
* @param idDelimiters delimiters between IDs
* @param transitivity support transitivity if true
* @throws IDMapperException if failed to read file
*/
public IDMapperText(final URL url,
final char[] dataSourceDelimiters,
final char[] idDelimiters,
final boolean transitivity) throws IDMapperException {
super(new IDMappingReaderFromText(url,
dataSourceDelimiters,
idDelimiters));
this.url = url;
this.dataSourceDelimiters = dataSourceDelimiters;
this.idDelimiters = idDelimiters;
setTransitivity(transitivity);
}
/**
* Free search is not supported for delimiter-text file.
* This will throw UnsupportedOperationException
* @param text ignored
* @param limit ignored
* @return does not return
* @throws IDMapperException will not be thrown
*/
public Set<Xref> freeSearch (String text, int limit) throws IDMapperException {
throw new UnsupportedOperationException();
}
/**
* Set transitivity support.
* @param transitivity support transitivity if true.
*/
public void setTransitivity(final boolean transitivity) {
this.transitivity = transitivity;
((IDMappingReaderFromText) reader).setTransitivity(transitivity);
}
/**
* Get transitivity support.
* @return true if support transitivity; false otherwise.
*/
public boolean getTransitivity() {
return transitivity;
}
/**
* Get {@link URL} of the file.
* @return {@link URL} of the file
*/
public URL getURL() {
return url;
}
/**
*
* @return delimiters between data sources
*/
public char[] getDataSourceDelimiters() {
return dataSourceDelimiters;
}
/**
*
* @return delimiters between data IDs
*/
public char[] getIDDelimiters() {
return idDelimiters;
}
/**
* Set delimiters between data sources.
* @param dataSourceDelimiters delimiters between data sources
*/
public void setDataSourceDelimiters(final char[] dataSourceDelimiters) {
((IDMappingReaderFromText)this.getIDMappingReader()).
setDataSourceDelimiters(dataSourceDelimiters);
this.dataSourceDelimiters = dataSourceDelimiters;
}
/**
* Set delimiters between data IDs.
* @param idDelimiters delimiters between data IDs
*/
public void setIDDelimiters(final char[] idDelimiters) {
((IDMappingReaderFromText)this.getIDMappingReader())
.setIDDelimiters(idDelimiters);
this.idDelimiters = idDelimiters;
}
public String toString()
{
return url.toString();
}
}