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 } 093 } 094 logger.trace("Releasing EcodFactory lock after getting version "+version); 095 096 return ecod; 097 } 098 } 099 100 /** 101 * removes SoftReferences which have already been garbage collected 102 */ 103 private static void releaseReferences() { 104 synchronized(versionedEcodDBs) { 105 Iterator<Entry<String, SoftReference<EcodDatabase>>> it = versionedEcodDBs.entrySet().iterator(); 106 while(it.hasNext()) { 107 Entry<String, SoftReference<EcodDatabase>> entry = it.next(); 108 SoftReference<EcodDatabase> ref = entry.getValue(); 109 if(ref.get() == null) { 110 logger.debug("Removed version {} from EcodFactory to save memory.",entry.getKey()); 111 it.remove(); 112 } 113 } 114 } 115 } 116 117 /** 118 * Updates the default version 119 * @param version 120 */ 121 public static void setEcodDatabase(String version) { 122 getEcodDatabase(version); 123 defaultVersion = version; 124 } 125 126 /** Can't instantiate */ 127 private EcodFactory() {} 128 129}