Java tutorial
/******************************************************************************* * Copyright C 2012, The Pistoia Alliance * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ******************************************************************************/ package org.helm.notation2; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.helm.chemtoolkit.CTKException; import org.helm.notation2.exception.ChemistryException; import org.helm.notation2.exception.EncoderException; import org.helm.notation2.exception.MonomerException; import org.helm.notation2.exception.MonomerLoadingException; import org.helm.notation2.tools.MonomerParser; import org.helm.notation2.wsadapter.MonomerStoreConfiguration; import org.helm.notation2.wsadapter.MonomerWSLoader; import org.jdom2.Attribute; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; import org.jdom2.output.Format; import org.jdom2.output.XMLOutputter; /** * This is a factory class to build monomer database from * MonomerDBGZEnconded.xml document * * @author zhangtianhong */ public class MonomerFactory { public static final String NOTATION_DIRECTORY = NotationConstant.NOTATION_DIRECTORY; public static final String MONOMER_CACHE_FILE_NAME = "MonomerCache.ser"; public static final String MONOMER_CACHE_FILE_PATH = NOTATION_DIRECTORY + System.getProperty("file.separator") + MONOMER_CACHE_FILE_NAME; public static final String MONOMER_DB_FILE_NAME = "MonomerDBGZEncoded.xml"; public static final String MONOMER_DB_FILE_PATH = NOTATION_DIRECTORY + System.getProperty("file.separator") + MONOMER_DB_FILE_NAME; public static final String MONOMER_DB_XML_RESOURCE = "resources/MonomerDBGZEncoded.xml"; public static final String MONOMER_DB_SCHEMA_RESOURCE = "resources/MonomerDBSchema.xsd"; public static final String XML_SCHEMA_VALIDATION_FEATURE = "http://apache.org/xml/features/validation/schema"; public static final String EXTERNAL_SCHEMA_LOCATION_KEY = "http://apache.org/xml/properties/schema/external-schemaLocation"; public static final String DEFAULT_NAME_SPACE = "lmr"; public static final String POLYMER_LIST_ELEMENT = "PolymerList"; public static final String POLYMER_ELEMENT = "Polymer"; public static final String POLYMER_TYPE_ATTRIBUTE = "polymerType"; public static final String ATTACHMENT_LIST_ELEMENT = "AttachmentList"; private static MonomerFactory instance; /** * First key is polymer Type, such as "RNA" Second key is monomer ID, such as * "A" */ private static Map<String, Map<String, Monomer>> monomerDB; // key is // monomer // SMILES, value // is Monomer private static Map<String, Monomer> smilesMonomerDB; // key is // AttachementID, // value is // Attachment private static Map<String, Attachment> attachmentDB; // private static Map<String, Map<String, Monomer>> externalMonomerDB; private static SAXBuilder builder; private static Logger logger = Logger.getLogger(MonomerFactory.class.toString()); private static boolean dbChanged = true; /** * retruns the monomer database * * @return Map as Map<String, Map<String, Monomer>> */ public synchronized Map<String, Map<String, Monomer>> getMonomerDB() { return getMonomerDB(true); } /** * returns the monomer database including monomers that where temporary marked * as new, else without those monomers * * @param includeNewMonomers * @return Map as Map<String, Map<String, Monomer>> */ public synchronized Map<String, Map<String, Monomer>> getMonomerDB(boolean includeNewMonomers) { if (includeNewMonomers) { return monomerDB; } else { Map<String, Map<String, Monomer>> reducedMonomerDB = new HashMap<String, Map<String, Monomer>>(); for (String polymerType : monomerDB.keySet()) { Map<String, Monomer> monomerMap = monomerDB.get(polymerType); reducedMonomerDB.put(polymerType, excludeNewMonomers(monomerMap)); } return reducedMonomerDB; } } protected MonomerStore monomerStore; /** * create a MonomerStore instance based on MonomerFactory's monomerDB and * smilesMonomerDB * * @return MonomerStore */ public synchronized MonomerStore getMonomerStore() { if (monomerStore == null) { monomerStore = new MonomerStore(monomerDB, smilesMonomerDB); } return monomerStore; } public synchronized Map<String, Attachment> getAttachmentDB() { return attachmentDB; } public synchronized Map<String, Monomer> getSmilesMonomerDB() { return getSmilesMonomerDB(true); } public synchronized Map<String, Monomer> getSmilesMonomerDB(boolean includeNewMonomers) { if (includeNewMonomers) { return smilesMonomerDB; } else { return excludeNewMonomers(smilesMonomerDB); } } private synchronized Map<String, Monomer> excludeNewMonomers(Map<String, Monomer> monomerMap) { Map<String, Monomer> reducedMonomerMap = new HashMap<String, Monomer>(); for (String identifier : monomerMap.keySet()) { Monomer monomer = monomerMap.get(identifier); if (!monomer.isNewMonomer()) { reducedMonomerMap.put(identifier, monomer); } } return reducedMonomerMap; } public synchronized List<String> getPolymerTypes() { List<String> l = new ArrayList<String>(); l.addAll(monomerDB.keySet()); Collections.sort(l); return l; } public synchronized List<String> getMonomerTypes() { List<String> monomerTypeList = new ArrayList<String>(); Object[] col = monomerDB.values().toArray(); for (int i = 0; i < col.length; i++) { Map<String, Monomer> map = (Map<String, Monomer>) col[i]; Monomer[] monomers = map.values().toArray(new Monomer[0]); for (int j = 0; j < monomers.length; j++) { if (!monomerTypeList.contains(monomers[j].getMonomerType())) { monomerTypeList.add(monomers[j].getMonomerType()); } } } Collections.sort(monomerTypeList); return monomerTypeList; } public synchronized Map<String, List<String>> getAttachmentLabelIDs() { Map<String, List<String>> labelMap = new HashMap<String, List<String>>(); // group attachments based on R value (label) Set<String> idSet = attachmentDB.keySet(); for (String id : idSet) { String label = attachmentDB.get(id).getLabel(); List<String> ids = labelMap.get(label); if (null == ids || ids.isEmpty()) { ids = new ArrayList<String>(); ids.add(id); labelMap.put(label, ids); } else { ids.add(id); } } // Sort ids in each R group Set<String> labelSet = labelMap.keySet(); for (String label : labelSet) { List<String> ids = labelMap.get(label); Collections.sort(ids); } return labelMap; } public static void setupBuilder() { URL schema = MonomerFactory.class.getResource(MONOMER_DB_SCHEMA_RESOURCE); builder = new SAXBuilder(false); // checks both well-formedness and // validity builder.setFeature(XML_SCHEMA_VALIDATION_FEATURE, true); builder.setProperty(EXTERNAL_SCHEMA_LOCATION_KEY, DEFAULT_NAME_SPACE + " " + schema.toString()); } private MonomerFactory() { } /** * Initialize MonomerCache and returns the singlton Factory class * * @return MonomerFactory * @throws ChemistryException * @throws CTKException * @throws org.helm.notation2.exception.MonomerException * @throws java.io.IOException * @throws org.jdom.JDOMException */ public static MonomerFactory getInstance() throws MonomerLoadingException, ChemistryException { if (null == instance) { refreshMonomerCache(); } else if (MonomerStoreConfiguration.getInstance().isUseWebservice() && MonomerStoreConfiguration.getInstance().isUpdateAutomatic()) { refreshMonomerCache(); } return instance; } public static void refreshMonomerCache() throws MonomerLoadingException, ChemistryException { initializeMonomerCache(); instance = new MonomerFactory(); } public static void setDBChanged(boolean isChanged) { dbChanged = isChanged; } /** * Returns whether one of the stored databases has changed, for example by * adding or removing monomers. * * @return true when database has changed else false */ public static boolean hasDBChanged() { return dbChanged; } public static void resetDBChanged() { dbChanged = false; } private static void serializeMonomerCache(MonomerCache monomerCache, String fileName) throws IOException { FileOutputStream fos = new FileOutputStream(fileName); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(monomerCache); oos.close(); fos.close(); } private static MonomerCache deserializeMonomerCache(String fileName) throws IOException, MonomerException { FileInputStream fis = new FileInputStream(fileName); ObjectInputStream ois = new ObjectInputStream(fis); MonomerCache cache = null; try { cache = (MonomerCache) ois.readObject(); // ensure monomers have their canonical SMILES set to what we store for (Map.Entry<String, Monomer> e : cache.getSmilesMonomerDB().entrySet()) { e.getValue().setCanSMILES(e.getKey()); } } catch (ClassNotFoundException cnfe) { throw new MonomerException("Unable to deserialize monomer cache from file"); } finally { ois.close(); } fis.close(); return cache; } /** * To add new monomer into monomerCache * * @param monomer */ public synchronized void addNewMonomer(Monomer monomer) throws IOException, MonomerException { monomer.setNewMonomer(true); addMonomer(monomerDB, smilesMonomerDB, monomer); dbChanged = true; } private void addMonomer(Map<String, Map<String, Monomer>> monomerDB, Map<String, Monomer> smilesMonomerDB, Monomer monomer) throws IOException, MonomerException { Map<String, Monomer> monomerMap = monomerDB.get(monomer.getPolymerType()); if (null == monomerMap) { Map<String, Monomer> map = new HashMap<String, Monomer>(); Monomer copyMonomer = DeepCopy.copy(monomer); map.put(monomer.getAlternateId(), copyMonomer); monomerDB.put(monomer.getPolymerType(), map); } else { if (!monomerMap.containsKey(monomer.getAlternateId())) { monomerMap.put(monomer.getAlternateId(), monomer); } } if (monomer.getCanSMILES() != null && monomer.getCanSMILES().length() > 0) { if (!smilesMonomerDB.containsKey(monomer.getCanSMILES())) { smilesMonomerDB.put(monomer.getCanSMILES(), monomer); } } dbChanged = true; } /** * Build an MonomerCache object with monomerDBXML String * * @param monomerDBXML * @return MonomerCache * @throws org.helm.notation2.exception.MonomerException * @throws java.io.IOException * @throws org.jdom.JDOMException * @throws ChemistryException * @throws CTKException */ public MonomerCache buildMonomerCacheFromXML(String monomerDBXML) throws MonomerException, IOException, JDOMException, ChemistryException, CTKException { ByteArrayInputStream bais = new ByteArrayInputStream(monomerDBXML.getBytes()); return buildMonomerCacheFromXML(bais); } /** * merge remote monomerCache with local monomerCache, will throw exception if * conflicts found. Client needs to resolve conflicts prior to calling merge * * @param remoteMonomerCache * @throws java.io.IOException * @throws org.helm.notation2.exception.MonomerException */ public synchronized void merge(MonomerCache remoteMonomerCache) throws IOException, MonomerException { Map<Monomer, Monomer> conflicts = getConflictedMonomerMap(remoteMonomerCache); if (conflicts.size() > 0) { throw new MonomerException("Local new monomer and remote monomer database conflict found"); } else { Map<String, Map<String, Monomer>> monoDB = remoteMonomerCache.getMonomerDB(); Set<String> polymerTypeSet = monoDB.keySet(); for (Iterator i = polymerTypeSet.iterator(); i.hasNext();) { String polymerType = (String) i.next(); Map<String, Monomer> map = monoDB.get(polymerType); Set<String> monomerSet = map.keySet(); for (Iterator it = monomerSet.iterator(); it.hasNext();) { String id = (String) it.next(); Monomer m = map.get(id); addMonomer(monomerDB, smilesMonomerDB, m); } } } dbChanged = true; } /** * replace local cache with remote one completely, may cause loss of data * * @param remoteMonomerCache * @throws java.io.IOException * @throws org.helm.notation2.exception.MonomerException */ public synchronized void setMonomerCache(MonomerCache remoteMonomerCache) throws IOException, MonomerException { monomerDB = remoteMonomerCache.getMonomerDB(); attachmentDB = remoteMonomerCache.getAttachmentDB(); smilesMonomerDB = remoteMonomerCache.getSmilesMonomerDB(); dbChanged = true; } /** * * @param remoteMonomerCache * @return localMonomer and remoteMonomer mismatch, key is local, value is * remote * @throws java.io.IOException * @throws org.helm.notation2.exception.MonomerException */ public synchronized Map<Monomer, Monomer> getConflictedMonomerMap(MonomerCache remoteMonomerCache) throws IOException, MonomerException { Map<String, Map<String, Monomer>> remoteMonomerDB = remoteMonomerCache.getMonomerDB(); Map<String, Monomer> remoteSmilesDB = remoteMonomerCache.getSmilesMonomerDB(); Map<Monomer, Monomer> map = new HashMap<Monomer, Monomer>(); List<Monomer> newMonomers = getNewMonomers(monomerDB); if (newMonomers.size() > 0) { for (int i = 0; i < newMonomers.size(); i++) { Monomer local = newMonomers.get(i); if (remoteMonomerDB.containsKey(local.getPolymerType())) { Map<String, Monomer> monomers = remoteMonomerDB.get(local.getPolymerType()); if (monomers.containsKey(local.getAlternateId())) { Monomer remote = monomers.get(local.getAlternateId()); if (local.getCanSMILES().equals(remote.getCanSMILES())) { logger.log(Level.INFO, "Perfect Match"); } else { map.put(local, remote); } } else { if (remoteSmilesDB.containsKey(local.getCanSMILES())) { Monomer remote = remoteSmilesDB.get(local.getCanSMILES()); map.put(local, remote); } else { logger.log(Level.INFO, "Really New"); } } } else { logger.log(Level.INFO, "New Polymer Type"); } } } return map; } private List<Monomer> getNewMonomers(Map<String, Map<String, Monomer>> monomerDB) { List<Monomer> l = new ArrayList<Monomer>(); Set<String> typeSet = monomerDB.keySet(); for (Iterator<String> i = typeSet.iterator(); i.hasNext();) { String polymerType = i.next(); Map<String, Monomer> map = monomerDB.get(polymerType); Object[] monomers = map.values().toArray(); for (int j = 0; j < monomers.length; j++) { Monomer m = (Monomer) monomers[j]; if (m.isNewMonomer()) { l.add(m); } } } return l; } private static MonomerCache buildMonomerCacheFromWebService() throws MonomerException, IOException, JDOMException { Map<String, Attachment> newAttachmentDB = fetchAttachmentDBFromWebService(); Map<String, Map<String, Monomer>> newMonomerDB; try { newMonomerDB = fetchMonomerDBFromWebService(newAttachmentDB); } catch (URISyntaxException | EncoderException e) { e.printStackTrace(); throw new IOException("URISyntaxException prevents fetching monomers from webservice."); } // Map<String, Map<String, Monomer>> newMonomerDB = // buildMonomerDB(polymerList); Map<String, Monomer> newSmilesMonomerDB = buildSmilesMonomerDB(newMonomerDB); MonomerCache cache = new MonomerCache(); cache.setMonomerDB(newMonomerDB); cache.setAttachmentDB(newAttachmentDB); cache.setSmilesMonomerDB(newSmilesMonomerDB); return cache; } private static Map<String, Attachment> fetchAttachmentDBFromWebService() { Map<String, Attachment> attachments = new HashMap<String, Attachment>(); Attachment att = new Attachment(); att.setAlternateId("R1-X"); att.setLabel("R1"); att.setCapGroupName("X"); attachments.put(att.getAlternateId(), att); att = new Attachment(); att.setAlternateId("R3-X"); att.setLabel("R3"); att.setCapGroupName("X"); attachments.put(att.getAlternateId(), att); att = new Attachment(); att.setAlternateId("R3-H"); att.setLabel("R3"); att.setCapGroupName("H"); att.setCapGroupSMILES("[*][H] |$_R3;$|"); attachments.put(att.getAlternateId(), att); att = new Attachment(); att.setAlternateId("R1-H"); att.setLabel("R1"); att.setCapGroupName("H"); att.setCapGroupSMILES("[*][H] |$_R1;$|"); attachments.put(att.getAlternateId(), att); att = new Attachment(); att.setAlternateId("R3-OH"); att.setLabel("R3"); att.setCapGroupName("OH"); att.setCapGroupSMILES("O[*] |$;_R3$|"); attachments.put(att.getAlternateId(), att); att = new Attachment(); att.setAlternateId("R2-H"); att.setLabel("R2"); att.setCapGroupName("H"); att.setCapGroupSMILES("[*][H] |$_R2;$|"); attachments.put(att.getAlternateId(), att); att = new Attachment(); att.setAlternateId("R2-X"); att.setLabel("R2"); att.setCapGroupName("X"); attachments.put(att.getAlternateId(), att); att = new Attachment(); att.setAlternateId("R2-OH"); att.setLabel("R2"); att.setCapGroupName("OH"); att.setCapGroupSMILES("O[*] |$;_R2$|"); attachments.put(att.getAlternateId(), att); att = new Attachment(); att.setAlternateId("R1-OH"); att.setLabel("R1"); att.setCapGroupName("OH"); att.setCapGroupSMILES("O[*] |$;_R1$|"); attachments.put(att.getAlternateId(), att); return attachments; } private static Map<String, Map<String, Monomer>> fetchMonomerDBFromWebService( Map<String, Attachment> attachments) throws IOException, URISyntaxException, EncoderException { Map<String, Map<String, Monomer>> monomerDB = new HashMap<String, Map<String, Monomer>>(); monomerDB.put("PEPTIDE", new MonomerWSLoader("PEPTIDE").loadMonomerStore(attachments)); monomerDB.put("RNA", new MonomerWSLoader("RNA").loadMonomerStore(attachments)); monomerDB.put("CHEM", new MonomerWSLoader("CHEM").loadMonomerStore(attachments)); return monomerDB; } private static MonomerCache buildMonomerCacheFromWS() throws MonomerException, IOException, JDOMException { return buildMonomerCacheFromWebService(); } private static MonomerCache buildMonomerCacheFromXML(InputStream monomerDBInputStream) throws MonomerException, IOException, JDOMException, ChemistryException, CTKException { if (null == builder) { setupBuilder(); } Document doc = builder.build(monomerDBInputStream); Element root = doc.getRootElement(); Element polymerList = root.getChild(POLYMER_LIST_ELEMENT, root.getNamespace()); Element attachmentList = root.getChild(ATTACHMENT_LIST_ELEMENT, root.getNamespace()); Map<String, Attachment> newAttachmentDB = buildAttachmentDB(attachmentList); Map<String, Map<String, Monomer>> newMonomerDB = buildMonomerDB(polymerList); Map<String, Monomer> newSmilesMonomerDB = buildSmilesMonomerDB(newMonomerDB); MonomerCache cache = new MonomerCache(); cache.setMonomerDB(newMonomerDB); cache.setAttachmentDB(newAttachmentDB); cache.setSmilesMonomerDB(newSmilesMonomerDB); return cache; } private static String buildMonomerDbXMLFromCache(MonomerCache cache) throws MonomerException { XMLOutputter outputer = new XMLOutputter(Format.getPrettyFormat()); StringBuilder sb = new StringBuilder(); sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + System.getProperty("line.separator") + "<MonomerDB xmlns=\"lmr\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + System.getProperty("line.separator")); Map<String, Map<String, Monomer>> mDB = cache.getMonomerDB(); Element polymerListElement = new Element(POLYMER_LIST_ELEMENT); Set<String> polymerTypeSet = mDB.keySet(); for (Iterator i = polymerTypeSet.iterator(); i.hasNext();) { String polymerType = (String) i.next(); Element polymerElement = new Element(POLYMER_ELEMENT); Attribute att = new Attribute(POLYMER_TYPE_ATTRIBUTE, polymerType); polymerElement.setAttribute(att); polymerListElement.getChildren().add(polymerElement); Map<String, Monomer> monomerMap = mDB.get(polymerType); Set<String> monomerSet = monomerMap.keySet(); for (Iterator it = monomerSet.iterator(); it.hasNext();) { String monomerID = (String) it.next(); Monomer m = monomerMap.get(monomerID); Element monomerElement = MonomerParser.getMonomerElement(m); polymerElement.getChildren().add(monomerElement); } } String polymerListString = outputer.outputString(polymerListElement); sb.append(polymerListString + System.getProperty("line.separator")); Map<String, Attachment> aDB = cache.getAttachmentDB(); Element attachmentListElement = new Element(ATTACHMENT_LIST_ELEMENT); Set<String> attachmentSet = aDB.keySet(); for (Iterator itr = attachmentSet.iterator(); itr.hasNext();) { String attachmentID = (String) itr.next(); Attachment attachment = aDB.get(attachmentID); Element attachmentElement = MonomerParser.getAttachementElement(attachment); attachmentListElement.getChildren().add(attachmentElement); } String attachmentListString = outputer.outputString(attachmentListElement); sb.append(attachmentListString); sb.append(System.getProperty("line.separator") + "</MonomerDB>" + System.getProperty("line.separator")); return sb.toString(); } /** * This method is called during startup, use serialized version if exists, * otherwise use XML version (First from local, then from jar) * * @throws ChemistryException * @throws CTKException * * @throws org.helm.notation2.exception.MonomerException * @throws java.io.IOException * @throws org.jdom.JDOMException */ private static void initializeMonomerCache() throws MonomerLoadingException, ChemistryException { MonomerCache cache = null; InputStream in = null; // check for webservice properties file if (MonomerStoreConfiguration.getInstance().isUseWebservice()) { try { cache = buildMonomerCacheFromWS(); validate(cache.getMonomerDB()); } catch (MonomerException | IOException | JDOMException | CTKException e) { throw new MonomerLoadingException( "Initializing MonomerStore failed because of " + e.getClass().getSimpleName(), e); } logger.log(Level.INFO, "WebService '' is used for monomer cache initialization"); } else if (MonomerStoreConfiguration.getInstance().isUseExternalMonomers()) { try { in = new FileInputStream(MONOMER_DB_FILE_PATH); cache = buildMonomerCacheFromXML(in); validate(cache.getMonomerDB()); logger.log(Level.INFO, MonomerStoreConfiguration.getInstance().getExternalMonomersPath() + " is used for monomer cache initialization"); } catch (Exception e) { logger.log(Level.INFO, "Unable to use local monomer DB file: " + MonomerStoreConfiguration.getInstance().getExternalMonomersPath()); } } else { File cacheFile = new File(MONOMER_CACHE_FILE_PATH); if (cacheFile.exists()) { try { cache = deserializeMonomerCache(MONOMER_CACHE_FILE_PATH); validate(cache.getMonomerDB()); logger.log(Level.INFO, MONOMER_CACHE_FILE_PATH + " is used for monomer cache initialization"); } catch (Exception e) { logger.log(Level.INFO, "Unable to use local monomer cache file: " + MONOMER_CACHE_FILE_NAME); cacheFile.delete(); logger.log(Level.INFO, "Deleted local monomer cache file: " + MONOMER_CACHE_FILE_NAME); } } File localMonomerDBFile = new File(MONOMER_DB_FILE_PATH); if (null == cache && localMonomerDBFile.exists()) { try { in = new FileInputStream(MONOMER_DB_FILE_PATH); cache = buildMonomerCacheFromXML(in); validate(cache.getMonomerDB()); logger.log(Level.INFO, MONOMER_DB_FILE_PATH + " is used for monomer cache initialization"); } catch (Exception e) { logger.log(Level.INFO, "Unable to use local monomer DB file: " + MONOMER_DB_FILE_NAME); localMonomerDBFile.delete(); logger.log(Level.INFO, "Deleted local monomer DB file: " + MONOMER_DB_FILE_NAME); } } if (null == cache) { in = MonomerFactory.class.getResourceAsStream(MONOMER_DB_XML_RESOURCE); try { System.out.println("BuildMonomerCacheFromXML"); cache = buildMonomerCacheFromXML(in); validate(cache.getMonomerDB()); } catch (MonomerException | IOException | JDOMException | CTKException e) { throw new MonomerLoadingException( "Initializing MonomerStore failed because of " + e.getClass().getSimpleName(), e); } logger.log(Level.INFO, MONOMER_DB_XML_RESOURCE + " is used for monomer cache initialization"); } } monomerDB = cache.getMonomerDB(); attachmentDB = cache.getAttachmentDB(); smilesMonomerDB = cache.getSmilesMonomerDB(); dbChanged = true; } /** * save monomerCache to disk file * * @throws java.io.IOException */ public void saveMonomerCache() throws IOException, MonomerException { File f = new File(NOTATION_DIRECTORY); if (!f.exists()) { f.mkdir(); } MonomerCache cache = new MonomerCache(); cache.setMonomerDB(getMonomerDB(false)); cache.setAttachmentDB(getAttachmentDB()); cache.setSmilesMonomerDB(getSmilesMonomerDB(false)); serializeMonomerCache(cache, MONOMER_CACHE_FILE_PATH); String monomerDbXML = buildMonomerDbXMLFromCache(cache); FileOutputStream fos = new FileOutputStream(MONOMER_DB_FILE_PATH); fos.write(monomerDbXML.getBytes()); fos.close(); } private static Map<String, Map<String, Monomer>> buildMonomerDB(Element polymerList) throws MonomerException, IOException, JDOMException, CTKException, ChemistryException { Map<String, Map<String, Monomer>> map = new HashMap<String, Map<String, Monomer>>(); List poplymers = polymerList.getChildren(); Iterator i = poplymers.iterator(); while (i.hasNext()) { Element polymer = (Element) i.next(); Attribute polymerType = polymer.getAttribute(POLYMER_TYPE_ATTRIBUTE); Map idMonomerMap = new HashMap<String, Monomer>(); List monomers = polymer.getChildren(); Iterator it = monomers.iterator(); while (it.hasNext()) { Element monomer = (Element) it.next(); Monomer m = MonomerParser.getMonomer(monomer); if (MonomerParser.validateMonomer(m)) { idMonomerMap.put(m.getAlternateId(), m); } } map.put(polymerType.getValue(), idMonomerMap); } return map; } private static Map<String, Attachment> buildAttachmentDB(Element attachmentList) throws MonomerException, IOException, JDOMException, ChemistryException { Map<String, Attachment> map = new HashMap<String, Attachment>(); List attachments = attachmentList.getChildren(); Iterator i = attachments.iterator(); while (i.hasNext()) { Element attachment = (Element) i.next(); Attachment att = MonomerParser.getAttachment(attachment); if (MonomerParser.validateAttachement(att)) { map.put(att.getAlternateId(), att); } } return map; } private static Map<String, Monomer> buildSmilesMonomerDB(Map<String, Map<String, Monomer>> monomerDB) { Map<String, Monomer> map = new HashMap<String, Monomer>(); Set<String> polymerSet = monomerDB.keySet(); for (Iterator i = polymerSet.iterator(); i.hasNext();) { String polymer = (String) i.next(); Map<String, Monomer> monomerMap = monomerDB.get(polymer); Set<String> monomerSet = monomerMap.keySet(); for (Iterator it = monomerSet.iterator(); it.hasNext();) { String monomerID = (String) it.next(); Monomer monomer = monomerMap.get(monomerID); String smiles = monomer.getCanSMILES(); try { Chemistry.getInstance().getManipulator().canonicalize(smiles); } catch (Exception e) { smiles = monomer.getCanSMILES(); } monomer.setCanSMILES(smiles); map.put(smiles, monomer); } } return map; } private static boolean validate(Map<String, Map<String, Monomer>> monomerDB) throws MonomerException, IOException, CTKException, ChemistryException { Set<String> polymers = monomerDB.keySet(); for (String polymer : polymers) { Map<String, Monomer> monomerMap = monomerDB.get(polymer); Set<String> monomers = monomerMap.keySet(); for (String monomer : monomers) { Monomer m = monomerMap.get(monomer); logger.info(m.getAlternateId()); MonomerParser.validateMonomer(m); } } return true; } public static void finalizeMonomerCache() { monomerDB = null; attachmentDB = null; smilesMonomerDB = null; dbChanged = true; instance = null; } }