/*
* BioJava development code
*
* This code may be freely distributed and modified under the
* terms of the GNU Lesser General Public Licence. This should
* be distributed with the code. If you do not have a copy,
* see:
*
* http://www.gnu.org/copyleft/lesser.html
*
* Copyright for this code is held jointly by the individual
* authors. These should be listed in @author doc comments.
*
* For more information on the BioJava project and its aims,
* or to join the biojava-l mailing list, visit the home page
* at:
*
* http://www.biojava.org/
*
*/
/**
*
*/
package org.biojava.nbio.structure;
import org.biojava.nbio.structure.align.util.HTTPConnectionTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.*;
/**
* Methods for getting the status of a PDB file (current, obsolete, etc)
* and for accessing different versions of the structure.
*
* All methods query the
*
* PDB website.
*
*
PDB supersessions form a directed acyclic graph, where edges point from an
* obsolete ID to the entry that directly superseded it. For example, here are
* edges from one portion of the graph:
*
* 1CAT -> 3CAT
* 3CAT -> 7CAT
* 3CAT -> 8CAT
*
*
The methods {@link #getReplaces(String, boolean) getReplaces(pdbId, false)}/
* {@link #getReplacement(String, boolean, boolean) getReplacement(pdbId, false, true)}
* just get the incoming/outgoing edges for a single node. The recursive versions
* ({@link #getReplaces(String, boolean) getReplaces(pdbId, true)},
* {@link #getReplacement(String, boolean, boolean) getReplacement(pdbId, true, false)})
* will do a depth-first search up/down the tree and return a list of all nodes ]
* reached.
*
*
Finally, the getCurrent() method returns a single PDB ID from among the
* results of
* {@link #getReplacement(String, boolean) getReplacement(pdbId, true)}.
* To be consistent with the old REST ordering, this is the PDB ID that occurs
* last alphabetically.
*
*
Results are cached to reduce server load.
*
* @author Spencer Bliven
* @author Amr AL-Hossary
* @since 3.0.2
*/
public class PDBStatus {
private static final Logger logger = LoggerFactory.getLogger(PDBStatus.class);
public static final String DEFAULT_PDB_SERVER = "www.rcsb.org";
public static final String PDB_SERVER_PROPERTY = "PDB.SERVER";
/**
* saves the returned results for further use.
*
*/
//TODO Use SoftReferences to allow garbage collection
private static Map> recordsCache= new Hashtable>();
/**
* Represents the status of PDB IDs. 'OBSOLETE' and 'CURRENT' are the most
* common.
* @author Spencer Bliven
*
*/
public enum Status {
OBSOLETE,
CURRENT,
AUTH,
HOLD,
HPUB,
POLC,
PROC,
REFI,
REPL,
WAIT,
WDRN,
MODEL,
UNKNOWN;
/**
*
* @param statusStr
* @return
* @throws IllegalArgumentException If the string is not recognized
*/
public static Status fromString(String statusStr) {
Status status;
String statusStrUpper = statusStr.toUpperCase();
if(statusStrUpper.equalsIgnoreCase("OBSOLETE"))
status = Status.OBSOLETE;
else if(statusStrUpper.equalsIgnoreCase("CURRENT"))
status = Status.CURRENT;
else if(statusStrUpper.equalsIgnoreCase("AUTH"))
status = Status.AUTH;
else if(statusStrUpper.equalsIgnoreCase("HOLD"))
status = Status.HOLD;
else if(statusStrUpper.equalsIgnoreCase("HPUB"))
status = Status.HPUB;
else if(statusStrUpper.equalsIgnoreCase("POLC"))
status = Status.POLC;
else if(statusStrUpper.equalsIgnoreCase("PROC"))
status = Status.PROC;
else if(statusStrUpper.equalsIgnoreCase("REFI"))
status = Status.REFI;
else if(statusStrUpper.equalsIgnoreCase("REPL"))
status = Status.REPL;
else if(statusStrUpper.equalsIgnoreCase("WAIT"))
status = Status.WAIT;
else if(statusStrUpper.equalsIgnoreCase("WDRN"))
status = Status.WDRN;
else if(statusStrUpper.equalsIgnoreCase("MODEL"))
status = Status.MODEL;
else if(statusStrUpper.equalsIgnoreCase("UNKNOWN"))
status = Status.UNKNOWN;
else {
throw new IllegalArgumentException("Unable to parse status '"+statusStrUpper+"'.");
}
return status;
}
}
/**
* Get the status of the PDB in question.
*
* @param pdbId
* @return The status, or null if an error occurred.
*/
public static Status getStatus(String pdbId) {
Status[] statuses = getStatus(new String[] {pdbId});
if(statuses != null) {
assert(statuses.length == 1);
return statuses[0];
} else {
return null;
}
}
/**
* Get the status of the a collection of PDBs in question in a single query.
*
* @see #getStatus(String)
* @param pdbIds
* @return The status array, or null if an error occurred.
*/
public static Status[] getStatus(String[] pdbIds) {
Status[] statuses = new Status[pdbIds.length];
List