001package org.biojava.bio.program.formats; 002 003import java.util.HashMap; 004import java.util.Iterator; 005import java.util.Map; 006 007import org.biojava.bio.BioException; 008import org.biojava.bio.EcNumber; 009import org.biojava.bio.program.tagvalue.ChangeTable; 010import org.biojava.bio.program.tagvalue.Formats; 011import org.biojava.bio.program.tagvalue.Parser; 012import org.biojava.utils.ClassTools; 013import org.biojava.utils.Services; 014import org.biojava.utils.lsid.LifeScienceIdentifier; 015import org.biojava.utils.lsid.LifeScienceIdentifierParseException; 016 017public class FormatTools { 018 private FormatTools() {} 019 020 private static Map LSID_2_FORMAT; 021 022 public static final ChangeTable.Changer EC_FROM_STRING = 023 new ChangeTable.Changer() { 024 public Object change(Object value) { 025 String sv = (String) value; 026 return EcNumber.Impl.valueOf(sv); 027 } 028 }; 029 030 /** 031 * Attempt to find aformat for a format identifer string. 032 * 033 * <p>The string will be resolved in the following way: 034 * <ol> 035 * <li>Treat the name as an LSID and search for a format class with that 036 * LSID.</li> 037 * <li>Load a class of that name</li> 038 * <li>Load a class in the package 039 * <code>org.biojava.bio.program.formats</code> with that name</li> 040 * <li>Load a class in that package after replacing each '.' in the name with 041 * "$" so that a search is made of inner classes.</li> 042 * </ol> 043 * <p> 044 * 045 * <p>It is not specified if the format returned is a new instance or not.</p> 046 * 047 * This method uses the service providor framework to find format providers. 048 * If you add formats to the core biojava distribution, you must add the 049 * class name to the file <code>biojava-live/resources/META-INF/services/org.biojava.bio.program.formats.Format</code>/ If you implement formats and 050 * place them in your own .jar files, you should put the class name in a 051 * similarly named file in your jar. This should mean that the format becomes 052 * automatically registered with the system. 053 * 054 * @param formatName the Stirng to use to find the format name 055 * @return a Format for that name 056 * @throws BioException if the format could not be resolved for some reason 057 */ 058 public static Format getFormat(String formatName) 059 throws BioException { 060 // fixme: should use somethign better than BioException 061 // should probaby go via jndi 062 063 Format format = null; 064 065 try { 066 LifeScienceIdentifier lsid = LifeScienceIdentifier.valueOf(formatName); 067 Map lsidResolvers = getLsid2Format(); 068 format = (Format) lsidResolvers.get(lsid); 069 } catch (LifeScienceIdentifierParseException e) { 070 // - it isn't an LSID I guess 071 } 072 073 if(format == null) { 074 Class formatClass = null; 075 076 try { 077 formatClass = ClassTools.getClassLoader(Parser.class).loadClass(formatName); 078 } catch (ClassNotFoundException cnfe1) { 079 } 080 081 if(formatClass == null) { 082 String fn = "org.biojava.bio.program.formats." + 083 formatName; 084 try { 085 formatClass = ClassTools.getClassLoader(Parser.class).loadClass(fn); 086 } catch (ClassNotFoundException cnfe2) { 087 } 088 } 089 090 if(formatClass == null) { 091 String fn = "org.biojava.bio.program.formats." + 092 formatName.replace('.', '$'); 093 try { 094 formatClass = ClassTools.getClassLoader(Parser.class).loadClass(fn); 095 } catch (ClassNotFoundException cnfe2) { 096 } 097 } 098 099 if(formatClass != null) { 100 try { 101 format = (Format) formatClass.newInstance(); 102 } catch (InstantiationException e) { 103 throw new BioException( 104 "Could not instantiate class for name " + formatName,e ); 105 } catch (IllegalAccessException e) { 106 throw new BioException( 107 "Could not instantiate class for name " + formatName , e); 108 } 109 } 110 } 111 112 if(format == null) { 113 throw new BioException("Could not resolve format name: " + formatName); 114 } 115 116 return format; 117 } 118 119 private static Map getLsid2Format() 120 throws BioException { 121 if(LSID_2_FORMAT == null) { 122 try { 123 LSID_2_FORMAT = new HashMap(); 124 ClassLoader loader = ClassTools.getClassLoader(Formats.class); 125 126 Iterator implNames = Services.getImplementationNames( 127 Format.class, loader ).iterator(); 128 129 while(implNames.hasNext()) { 130 String name = (String) implNames.next(); 131 Class clazz = loader.loadClass(name); 132 Format format = (Format) clazz.newInstance(); 133 LSID_2_FORMAT.put(format.getLSID(), format); 134 } 135 } catch (Exception e) { 136 throw new BioException("Could not load service provider info for formats",e); 137 } 138 } 139 140 return LSID_2_FORMAT; 141 } 142}