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 */ 021 022package org.biojavax; 023import java.util.Arrays; 024import java.util.HashMap; 025import java.util.Iterator; 026import java.util.LinkedHashMap; 027import java.util.List; 028import java.util.Map; 029 030 031import org.biojavax.bio.seq.DummyRichSequenceHandler; 032import org.biojavax.bio.seq.PositionResolver; 033import org.biojavax.bio.seq.RichSequenceHandler; 034import org.biojavax.bio.seq.PositionResolver.AverageResolver; 035import org.biojavax.ontology.ComparableOntology; 036import org.biojavax.ontology.SimpleComparableOntology; 037 038 039/** 040 * Runs a service that builds rich objects, and provides some default values 041 * for things like default ontology, default namespace, etc. 042 * @author Richard Holland 043 * @since 1.5 044 */ 045public class RichObjectFactory { 046 047 private static RichObjectBuilder builder = new SimpleRichObjectBuilder(); 048 049 private static String defaultOntologyName = "biojavax"; 050 private static String defaultNamespaceName = "lcl"; 051 private static PositionResolver defaultPositionResolver = new AverageResolver(); 052 private static CrossReferenceResolver defaultCrossRefResolver = new DummyCrossReferenceResolver(); 053 private static RichSequenceHandler defaultRichSequenceHandler = new DummyRichSequenceHandler(); 054 055 // the LRU cache - keys are classes, entries are maps of param sets to objects 056 private static int defaultLRUcacheSize = 20; 057 private static Map LRUcacheSizes = new HashMap(); 058 private static Map cache = new HashMap(); 059 private final static Map applicationClassMap = new HashMap(); 060 061 // Constructor is private as this is all static. 062 private RichObjectFactory() {} 063 064 /** 065 * Sets the builder to use when instantiating new Rich objects. The basic, 066 * default, one is a SimpleRichObjectBuilder, which just calls the constructor. 067 * Another useful one is BioSQLRichObjectBuilder, which attempts to load 068 * objects from the database. The latter is required if you are working with 069 * Hibernate as it will not work without it. 070 * @param b the builder to use. 071 * @see SimpleRichObjectBuilder 072 * @see org.biojavax.bio.db.biosql.BioSQLRichObjectBuilder 073 */ 074 public static synchronized void setRichObjectBuilder(RichObjectBuilder b) { 075 builder = b; 076 } 077 078 /** 079 * Delegates to a RichObjectBuilder to construct/retrieve the object, and returns it. 080 * To increase efficiency, it keeps a list of recently requested objects. If it 081 * receives further requests for the same object, it returns them from the cache. The 082 * size of the cache can be altered using setLRUCacheSize(). The default cache size is 20 083 * objects for each type of class requested. 084 * @param clazz the class to build 085 * @param params the parameters to pass to the class' constructor 086 * @return the instantiated object 087 */ 088 public static synchronized Object getObject(final Class clazz, Object[] params) { 089 List paramsList = Arrays.asList(params); 090 final Class applicationClass = getApplicationClass(clazz); 091 if (!cache.containsKey(applicationClass)) { 092 int LRUcacheSize = defaultLRUcacheSize; 093 if (LRUcacheSizes.containsKey(applicationClass)) LRUcacheSize = ((Integer)LRUcacheSizes.get(applicationClass)).intValue(); 094 else LRUcacheSizes.put(applicationClass,new Integer(LRUcacheSize)); 095 cache.put(applicationClass, new LinkedHashMap(LRUcacheSize, 0.75f, true) { 096 protected boolean removeEldestEntry(Map.Entry eldest) { 097 return this.size() > ((Integer)LRUcacheSizes.get(applicationClass)).intValue(); 098 } 099 }); 100 } 101 Map m = (Map)cache.get(applicationClass); 102 if (!m.containsKey(paramsList)) { 103 m.put(paramsList,builder.buildObject(applicationClass, paramsList)); 104 } 105 return m.get(paramsList); 106 } 107 108 private final static Map getApplicationClassMap() { 109 return applicationClassMap; 110 } 111 112 /** 113 * Allow application to override the default biojava class created in getObject - subclass restriction is checked in the builder. 114 * @param theBiojavaClass one of the well-known builder classes: SimpleNamespace, SimpleComparableOntology, SimpleNCBITaxon, SimpleCrossRef, or SimpleDocRef 115 * @param theApplicationClass - a subclass of theBiojavaClass 116 */ 117 public final static void setApplicationClass(final Class theBiojavaClass, final Class theApplicationClass) { 118 if (theApplicationClass==null || theBiojavaClass.isAssignableFrom(theApplicationClass) == false) throw new IllegalArgumentException("RichObjectFactory.setApplicationClass-theApplicationClass: <"+theApplicationClass+"> must be assignable to the biojava class: <"+theBiojavaClass+">"); 119 getApplicationClassMap().put(theBiojavaClass, theApplicationClass); 120 } 121 122 private final static Class getApplicationClass(final Class theBiojavaClass) { 123 final Class applicationClass = (Class) getApplicationClassMap().get(theBiojavaClass); 124 return applicationClass!=null?applicationClass:theBiojavaClass; 125 } 126 127 /** 128 * Removes all objects from the LRU cache. 129 */ 130 public static synchronized void clearLRUCache(){ 131 cache.clear(); 132 } 133 134 /** 135 * Removes all objects of the specified class from the LRU cache. 136 * @param clazz The class of the objects to remove. 137 */ 138 public static synchronized void clearLRUCache(Class clazz){ 139 cache.remove(clazz); 140 } 141 142 /** 143 * Sets the size of the LRU cache. This is the size per class of object requested, so 144 * if you set it to 20 and request 3 different types of object, you will get 20*3=60 145 * entries in the cache. The default cache size is 20. Setting this value will undo 146 * any previous changes made using the setLRUCacheSize(Class,int) method below, but will not 147 * override future ones. 148 * @param size the size of the cache. 149 */ 150 public static void setLRUCacheSize(int size) { 151 defaultLRUcacheSize = size; 152 for (Iterator i = LRUcacheSizes.keySet().iterator(); i.hasNext(); ) LRUcacheSizes.put(i.next(), new Integer(size)); 153 } 154 155 /** 156 * Sets the size of the LRU cache. This is the size for the specific class of object 157 * requested, so does not affect the size of caches of other objects. 158 * If this method is not called, then the cache size defaults to 20, or whatever value 159 * was passed to setLRUCacheSize(int) above. 160 * @param size the size of the cache. 161 */ 162 public static void setLRUCacheSize(Class clazz, int size) { 163 LRUcacheSizes.put(clazz,new Integer(size)); 164 } 165 166 /** 167 * Sets the default namespace name to use when loading sequences. Defaults to "lcl". 168 * @param name the namespace name to use. 169 */ 170 public static void setDefaultNamespaceName(String name) { defaultNamespaceName = name; } 171 172 /** 173 * Sets the default ontology name to use when loading sequences. Defaults to "biojavax". 174 * @param name the ontology name to use. 175 */ 176 public static void setDefaultOntologyName(String name) { defaultOntologyName = name; } 177 178 /** 179 * Sets the default position resolver to use when creating new rich feature locations. 180 * Defaults to the AverageResolver 181 * @param pr the position resolver to use. 182 * @see org.biojavax.bio.seq.PositionResolver 183 * @see org.biojavax.bio.seq.PositionResolver.AverageResolver 184 * @see org.biojavax.bio.seq.RichLocation 185 */ 186 public static void setDefaultPositionResolver(PositionResolver pr) { defaultPositionResolver = pr; } 187 188 /** 189 * Sets the default crossref resolver to use when resolving remote entries. 190 * Defaults to the DummyCrossReferenceResolver. 191 * @param crr the resolver to use. 192 * @see org.biojavax.CrossReferenceResolver 193 * @see org.biojavax.DummyCrossReferenceResolver 194 */ 195 public static void setDefaultCrossReferenceResolver(CrossReferenceResolver crr) { defaultCrossRefResolver = crr; } 196 197 /** 198 * Sets the default sequence handler to use when performing sequence manipulation. 199 * Defaults to the DummyRichSequenceHandler. 200 * @param rsh the resolver to use. 201 * @see org.biojavax.bio.seq.RichSequenceHandler 202 * @see org.biojavax.bio.seq.DummyRichSequenceHandler 203 */ 204 public static void setDefaultRichSequenceHandler(RichSequenceHandler rsh) { defaultRichSequenceHandler = rsh; } 205 206 /** 207 * Returns the default namespace object. Defaults to "lcl". 208 * @return the default namespace. 209 */ 210 public static Namespace getDefaultNamespace() { 211 return (Namespace)getObject(SimpleNamespace.class, new Object[]{defaultNamespaceName}); 212 } 213 214 /** 215 * Returns the default ontology object. Defaults to "biojavax". 216 * @return the default ontology. 217 */ 218 public static ComparableOntology getDefaultOntology() { 219 return (ComparableOntology)getObject(SimpleComparableOntology.class, new Object[]{defaultOntologyName}); 220 } 221 222 /** 223 * Returns the default position resolver object. Defaults to PositionResolver.AverageResolver 224 * @return the default position resolver. 225 * @see org.biojavax.bio.seq.PositionResolver.AverageResolver 226 */ 227 public static PositionResolver getDefaultPositionResolver() { return defaultPositionResolver; } 228 229 /** 230 * Returns the default cross ref resolver object. Defaults to DummyCrossReferenceResolver 231 * @return the default resolver. 232 * @see org.biojavax.DummyCrossReferenceResolver 233 */ 234 public static CrossReferenceResolver getDefaultCrossReferenceResolver() { return defaultCrossRefResolver; } 235 236 /** 237 * Returns the default sequence resolver object. Defaults to DummyRichSequenceHandler. 238 * @return the default resolver. 239 * @see org.biojavax.bio.seq.DummyRichSequenceHandler 240 */ 241 public static RichSequenceHandler getDefaultRichSequenceHandler() { return defaultRichSequenceHandler; } 242 243// commenting out for the moment, since it prevents core from compiling. 244// TODO: move to BioSql module 245// /** 246// * A utility method that configures the RichObjectFactory for use with a Hibernate session. 247// * @param session an object containing a Hibernate session. 248// */ 249// public static void connectToBioSQL(Object session) { 250// clearLRUCache(); 251// RichObjectFactory.setRichObjectBuilder(new BioSQLRichObjectBuilder(session)); 252// RichObjectFactory.setDefaultCrossReferenceResolver(new BioSQLCrossReferenceResolver(session)); 253// RichObjectFactory.setDefaultRichSequenceHandler(new BioSQLRichSequenceHandler(session)); 254// } 255}