001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.nbio.structure.domain;
022
023import java.io.IOException;
024import java.io.InputStream;
025import java.net.MalformedURLException;
026import java.net.URL;
027import java.util.List;
028import java.util.Map;
029import java.util.SortedSet;
030import java.util.TreeSet;
031
032import org.biojava.nbio.structure.StructureException;
033import org.biojava.nbio.structure.align.client.JFatCatClient;
034import org.biojava.nbio.structure.align.client.StructureName;
035import org.biojava.nbio.structure.align.util.HTTPConnectionTools;
036import org.biojava.nbio.structure.scop.ScopDatabase;
037import org.biojava.nbio.structure.scop.ScopDomain;
038import org.biojava.nbio.structure.scop.ScopFactory;
039import org.biojava.nbio.structure.scop.server.XMLUtil;
040import org.slf4j.Logger;
041import org.slf4j.LoggerFactory;
042
043
044/**
045 * A DomainProvider that uses a mixture of SCOP and PDP domains.
046 *
047 * SCOP domains are preferred, with PDP providing a backup for structures where
048 * SCOP has not been assigned.
049 *
050 * As of 2015, this class is equivalent to the method used by RCSB to define
051 * representatives for structural similarity comparisons.
052 */
053public class RemoteDomainProvider extends SerializableCache<String,SortedSet<String>> implements DomainProvider{
054        private static final Logger logger = LoggerFactory.getLogger(RemoteDomainProvider.class);
055
056        public String url = RemotePDPProvider.DEFAULT_SERVER;
057
058        ScopDatabase scop;
059        PDPProvider pdp;
060
061        private static String CACHE_FILE_NAME = "remotedomaincache.ser";
062
063
064        public RemoteDomainProvider(){
065                // equivalent to this(false) but without IOException
066                super(CACHE_FILE_NAME);
067                disableCache();
068                scop = ScopFactory.getSCOP();
069                pdp = new RemotePDPProvider();
070        }
071
072        /** initialize this provider with caching enabled
073         *
074         * @param cache
075         * @throws IOException
076         */
077        public RemoteDomainProvider(boolean cache) throws IOException{
078                super(CACHE_FILE_NAME);
079
080                if( ! cache) {
081                        disableCache();
082                        //} else if ( serializedCache.keySet().size() < 20000){
083                } else {
084                        // always load the representative assignments from server...
085                        // this makes sure we always have the latest assignments
086                        loadRepresentativeDomainAssignments();
087                }
088
089                scop = ScopFactory.getSCOP();
090                pdp = new RemotePDPProvider(cache);
091        }
092
093        /** Requests the domain assignments for the current PDB IDs from the PDB.
094         * @throws IOException if the server cannot be reached
095         *
096         */
097        private void loadRepresentativeDomainAssignments() throws IOException {
098                AssignmentXMLSerializer results = null;
099                try {
100                        URL u = new URL(url + "getRepresentativeDomains");
101                        logger.info("Fetching {}",u);
102                        InputStream response = HTTPConnectionTools.getInputStream(u);
103                        String xml = JFatCatClient.convertStreamToString(response);
104                        results  = AssignmentXMLSerializer.fromXML(xml);
105
106                        Map<String,String> data = results.getAssignments();
107                        logger.info("got {} ranges from server.",data.size());
108                        for (String key: data.keySet()){
109                                String range = data.get(key);
110
111                                // work around list in results;
112
113                                String[] spl = range.split(",");
114                                SortedSet<String> value = new TreeSet<String>();
115
116                                for (String s : spl){
117                                        value.add(s);
118
119                                }
120                                serializedCache.put(key, value);
121                        }
122
123                } catch (MalformedURLException e){
124                        logger.error("Malformed Domain server: "+url,e);
125                        throw new IllegalArgumentException("Invalid Server: "+url, e);
126                }
127        }
128
129        @Override
130        public SortedSet<String> getDomainNames(String name) throws IOException, StructureException {
131
132
133                if ( name.length() < 4)
134                        throw new IllegalArgumentException("Can't interpret IDs that are shorter than 4 residues!");
135
136                if ( serializedCache != null){
137                        if ( serializedCache.containsKey(name)){
138                                return serializedCache.get(name);
139                        }
140                }
141
142                StructureName n = new StructureName(name);
143
144                List<ScopDomain>scopDomains = scop.getDomainsForPDB(n.getPdbId());
145
146                String chainID = n.getChainId();
147
148                if ( scopDomains == null || scopDomains.size() == 0){
149                        SortedSet<String> data= getPDPDomains(n);
150                        cache(name,data);
151                        return data;
152                } else {
153                        SortedSet<String> r = new TreeSet<String>();
154                        for ( ScopDomain d: scopDomains){
155                                StructureName s = new StructureName(d.getScopId());
156
157                                if( chainID == null){
158                                        r.add(s.getIdentifier());
159
160                                } else if( s.getChainId().equalsIgnoreCase(n.getChainId())) {
161                                        // SCOP IDS are case insensitive...
162                                        r.add(s.getIdentifier());
163                                }
164                        }
165                        cache(name,r);
166                        return r;
167                }
168
169
170
171        }
172
173
174
175
176        private SortedSet<String> getPDPDomains(StructureName n) throws IOException, StructureException {
177                SortedSet<String> pdpDomains = pdp.getPDPDomainNamesForPDB(n.getPdbId());
178
179                SortedSet<String> r = new TreeSet<String>();
180                String chainID = n.getChainId();
181                for ( String s : pdpDomains){
182                        StructureName d = new StructureName(s);
183                        if ( chainID == null)
184                                r.add(s);
185                        else if ( d.getChainId().equals(n.getChainId())){
186                                r.add(s);
187                        }
188                }
189                logger.info(n + " got PDP domains: "+ r);
190                return r;
191        }
192
193        public static void main(String[] args) throws IOException, StructureException{
194                String name ="3KIH.A";
195                RemoteDomainProvider me = new RemoteDomainProvider(true);
196                System.out.println(me.getDomainNames(name));
197                StructureName n = new StructureName(name);
198                System.out.println(n);
199                //System.out.println(new  AtomCache().getStructure(name));
200                me.flushCache();
201        }
202
203        @Override
204        public void flushCache() {
205                super.flushCache();
206                if ( pdp instanceof RemotePDPProvider){
207                        RemotePDPProvider remotePDP = (RemotePDPProvider)pdp;
208                        remotePDP.flushCache();
209                }
210        }
211
212        @Override
213        public SortedSet<String> getRepresentativeDomains() throws IOException {
214
215                String url = "http://source.rcsb.org/jfatcatserver/domains/getRepresentativeDomainNames";
216                SortedSet<String> domainRanges = null;
217                try {
218                        URL u = new URL(url);
219                        logger.info("Fetching {}",url);
220                        InputStream response = HTTPConnectionTools.getInputStream(u);
221                        String xml = JFatCatClient.convertStreamToString(response);
222                        //System.out.println(xml);
223                        domainRanges = XMLUtil.getDomainRangesFromXML(xml);
224                } catch (MalformedURLException e){
225                        logger.error("Malformed Domain server: "+url,e);
226                        throw new IllegalArgumentException("Invalid Server: "+url, e);
227                }
228                return domainRanges;
229        }
230
231
232
233
234}