// 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.webservice.picr;
import java.net.URL;
import java.net.URLConnection;
import java.io.InputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.bridgedb.AbstractIDMapperCapabilities;
import org.bridgedb.BridgeDb;
import org.bridgedb.DataSource;
import org.bridgedb.IDMapper;
import org.bridgedb.IDMapperCapabilities;
import org.bridgedb.IDMapperException;
import org.bridgedb.impl.InternalUtils;
import org.bridgedb.webservice.IDMapperWebservice;
import org.bridgedb.Xref;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
//TODO: implements AttributeMapper
public class IDMapperPicrRest extends IDMapperWebservice
{
static
{
BridgeDb.register ("idmapper-picr-rest", new Driver());
}
private String baseUrl = "http://www.ebi.ac.uk/Tools/picr/rest/";
private boolean onlyActive;
private Set<DataSource> supportedDatabases = new HashSet<DataSource>();
/**
*
* @param onlyActive using only active mappings if true
*/
public IDMapperPicrRest(boolean onlyActive) throws IDMapperException
{
List<String> dbs;
try {
dbs = getMappedDataBaseNames();
} catch (Exception e) {
throw new IDMapperException(e);
}
for (String s : dbs)
{
supportedDatabases.add(DataSource.getByFullName(s));
}
this.onlyActive = onlyActive;
}
/**
*
* @return true if using only active mappings; false otherwise
*/
public boolean getOnlyActive() {
return onlyActive;
}
/**
*
* @param onlyActive using only active mappings if true
*/
public void setOnlyActive(boolean onlyActive) {
this.onlyActive = onlyActive;
}
private static class Driver implements org.bridgedb.Driver
{
private Driver() { } // prevent outside instantiation
public IDMapper connect(String location) throws IDMapperException
{
Map<String, String> args =
InternalUtils.parseLocation(location, "only-active");
boolean isOnlyActive = true;
if (args.containsKey("only-active"))
{
isOnlyActive = Boolean.parseBoolean(args.get("only-active"));
}
return new IDMapperPicrRest(isOnlyActive);
}
}
private boolean closed = false;
public void close() throws IDMapperException
{
closed = true;
}
/**
* free search is not supported
*/
public Set<Xref> freeSearch(String text, int limit)
throws IDMapperException {
throw new UnsupportedOperationException();
}
private List<String> getMappedDataBaseNames() throws Exception {
String url = baseUrl + "getMappedDatabaseNames";
InputStream is = InternalUtils.getInputStream(url);
// Get the result as XML document.
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
final Document doc = builder.parse(is);
NodeList nodes = doc.getElementsByTagName("ns2:mappedDatabases");
int n = nodes.getLength();
List<String> dbs = new ArrayList<String>(n);
for (int i=0; i<n; i++) {
Node node = nodes.item(i);
dbs.add(node.getTextContent());
}
return dbs;
}
private class PICRCapabilities extends AbstractIDMapperCapabilities
{
public PICRCapabilities()
{
super (supportedDatabases, false, null);
}
}
private PICRCapabilities picrCapabilities = new PICRCapabilities();
public IDMapperCapabilities getCapabilities()
{
return picrCapabilities;
}
public boolean isConnected()
{
return !closed;
}
/**
* {@inheritDoc}
*/
public Map<Xref, Set<Xref>> mapID(Collection<Xref> srcXrefs,
DataSource... tgtDataSources) throws IDMapperException
{
return InternalUtils.mapMultiFromSingle(this, srcXrefs, tgtDataSources);
}
/**
* {@inheritDoc}
*/
@Override public Set<Xref> mapID(Xref xref,
DataSource... tgtDataSources) throws IDMapperException
{
if (xref==null) {
throw new NullPointerException(
"srcXrefs or tgtDataSources cannot be null.");
}
Set<Xref> result = new HashSet<Xref>();
// remove unsupported data sources
Set<String> tgtDss = new HashSet<String>();
if (tgtDataSources.length > 0) {
for (DataSource ds : tgtDataSources) {
if (supportedDatabases.contains(ds)) {
tgtDss.add(ds.getFullName());
}
}
} else {
for (DataSource ds : supportedDatabases) {
tgtDss.add(ds.getFullName());
}
}
DataSource ds = xref.getDataSource();
if (!supportedDatabases.contains(ds))
return result;
Set<String> databases = new HashSet<String>(tgtDss.size()+1);
databases.addAll(tgtDss);
databases.add(ds.getFullName()); // add the source ds
String accession = xref.getId();
try {
result = mappingService(accession, databases);
} catch (Exception e) {
throw new IDMapperException (e);
}
return result;
}
/**
* {@inheritDoc}
*/
public boolean xrefExists(Xref xref) throws IDMapperException
{
DataSource ds = xref.getDataSource();
if (!supportedDatabases.contains(ds))
return false;
Set<String> dss = new HashSet<String>();
dss.add(ds.getFullName());
Set<Xref> xrefs = null;
try {
xrefs = mappingService(xref.getId(), dss);
} catch (Exception e) {
e.printStackTrace();
}
return xrefs!=null && !xrefs.isEmpty();
}
private Set<Xref> mappingService(String accession, Set<String> databases)
throws IOException, SAXException, ParserConfigurationException
{
Set<Xref> result = new HashSet<Xref>();
StringBuilder url = new StringBuilder(baseUrl);
url.append("getUPIForAccession?");
if (!onlyActive) {
url.append("onlyactive=false&");
}
url.append("accession=");
url.append(accession);
for (String database : databases) {
url.append("&database=");
url.append(database);
}
final Document doc;
InputStream is = InternalUtils.getInputStream(url.toString());
if (is.available()<=0) return result;
// Get the result as XML document.
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
doc = builder.parse(is);
String[] tags = new String[] {"identicalCrossReferences"
, "logicalCrossReferences"};
List<Node> nodes = new ArrayList<Node>();
for (String tag : tags) {
NodeList nodeList = doc.getElementsByTagName(tag);
int n = nodeList.getLength();
for (int i=0; i<n; i++) {
nodes.add(nodeList.item(i));
}
}
for (Node node : nodes) {
NodeList children = node.getChildNodes();
int nc = children.getLength();
String tgtAcc = null;
String tgtDb = null;
for (int j=0; j<nc; j++) {
Node child = children.item(j);
if ("accession".equals(child.getNodeName()))
{
tgtAcc = child.getTextContent();
}
else if ("databaseName".equals(child.getNodeName()))
{
tgtDb = child.getTextContent();
}
if (tgtAcc!=null && tgtDb!=null) {
DataSource tgtDs = DataSource.getByFullName(tgtDb);
result.add(new Xref(tgtAcc, tgtDs));
break;
}
}
}
return result;
}
}