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.ecod; 022 023import java.io.IOException; 024import java.lang.ref.SoftReference; 025import java.util.Collections; 026import java.util.HashMap; 027import java.util.Iterator; 028import java.util.Map; 029import java.util.Map.Entry; 030 031import org.biojava.nbio.structure.align.util.UserConfiguration; 032import org.biojava.nbio.structure.cath.CathFactory; 033import org.biojava.nbio.structure.scop.ScopFactory; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036 037/** 038 * Controls global {@link EcodDatabase EcodDatabases} being used. 039 * Implements a multiton pattern through {@link #getEcodDatabase(String)}, 040 * and a singleton pattern through {@link #getEcodDatabase()}. 041 * @author Spencer Bliven 042 * @see ScopFactory 043 * @see CathFactory 044 * @see EcodInstallation 045 */ 046public class EcodFactory { 047 048 private static final Logger logger = LoggerFactory.getLogger(EcodFactory.class); 049 050 public static final String DEFAULT_VERSION = EcodInstallation.DEFAULT_VERSION; 051 052 private static Map<String, SoftReference<EcodDatabase>> versionedEcodDBs = 053 Collections.synchronizedMap(new HashMap<String, SoftReference<EcodDatabase>>()); 054 private static String defaultVersion = EcodInstallation.DEFAULT_VERSION; 055 056 /** 057 * Returns the (singleton) database for the current default version 058 */ 059 public static EcodDatabase getEcodDatabase() { 060 return getEcodDatabase(defaultVersion); 061 } 062 063 public static EcodDatabase getEcodDatabase(String version) { 064 if( version == null ) 065 version = defaultVersion; 066 067 logger.trace("Waiting for EcodFactory lock to get version "+version); 068 synchronized(versionedEcodDBs) { 069 logger.trace("Got EcodFactory lock to get version "+version); 070 071 releaseReferences(); 072 073 SoftReference<EcodDatabase> ecodRef = versionedEcodDBs.get(version.toLowerCase()); 074 EcodDatabase ecod = null; 075 if(ecodRef != null) { 076 ecod = ecodRef.get(); 077 } 078 if( ecod == null ) { 079 logger.debug("Creating new {}, version {}",EcodInstallation.class.getSimpleName(),version); 080 String cacheDir = new UserConfiguration().getCacheFilePath(); 081 ecod = new EcodInstallation(cacheDir, version); 082 versionedEcodDBs.put(version.toLowerCase(), new SoftReference<EcodDatabase>(ecod)); 083 084 // If the parsed version differed from that requested, add that too 085 // Note that getVersion() may trigger file parsing 086 try { 087 if( ! versionedEcodDBs.containsKey(ecod.getVersion().toLowerCase()) ) { 088 versionedEcodDBs.put(ecod.getVersion().toLowerCase(),new SoftReference<EcodDatabase>(ecod)); 089 } 090 } catch (IOException e) { 091 // For parsing errors, just use the requested version 092 // TODO What about corrupted downloading errors?? Amr 093 logger.warn("Could not get Ecod version, or file is corrupted", e); 094 return null; 095 } 096 } 097 logger.trace("Releasing EcodFactory lock after getting version "+version); 098 099 return ecod; 100 } 101 } 102 103 /** 104 * removes SoftReferences which have already been garbage collected 105 */ 106 private static void releaseReferences() { 107 synchronized(versionedEcodDBs) { 108 Iterator<Entry<String, SoftReference<EcodDatabase>>> it = versionedEcodDBs.entrySet().iterator(); 109 while(it.hasNext()) { 110 Entry<String, SoftReference<EcodDatabase>> entry = it.next(); 111 SoftReference<EcodDatabase> ref = entry.getValue(); 112 if(ref.get() == null) { 113 logger.debug("Removed version {} from EcodFactory to save memory.",entry.getKey()); 114 it.remove(); 115 } 116 } 117 } 118 } 119 120 /** 121 * Updates the default version 122 * @param version 123 */ 124 public static void setEcodDatabase(String version) { 125 getEcodDatabase(version); 126 defaultVersion = version; 127 } 128 129 /** Can't instantiate */ 130 private EcodFactory() {} 131 132}