/* * EuroCarbDB, a framework for carbohydrate bioinformatics * * Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * A copy of this license accompanies this distribution in the file LICENSE.txt. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * Last commit: $Rev: 1210 $ by $Author: glycoslave $ on $Date:: 2009-06-12 #$ */ package org.eurocarbdb.application.glycanbuilder; import java.awt.print.*; import java.util.*; import java.io.*; import org.w3c.dom.*; /** A BuilderWorkspace is a container for all the documents, dictionaries and options that are used in the GlycanBuilder application. During initialization the workspace read all the configuration from a file (if provided) and initialize all static dictionaries and options. A workspace must be initialized before any other action using the GlycanBuilder classes. @author Alessio Ceroni (a.ceroni@imperial.ac.uk) */ public class BuilderWorkspace extends BaseDocument implements BaseWorkspace, BaseDocument.DocumentChangeListener { protected static boolean loaded = false; protected boolean autosave; // style protected ResiduePlacementDictionary theResiduePlacementDictionary; protected ResidueStyleDictionary theResidueStyleDictionary; protected LinkageStyleDictionary theLinkageStyleDictionary; // configuration protected Configuration theConfiguration; protected FileHistory theFileHistory; protected ResidueHistory theResidueHistory; protected MassOptions theMassOptions; protected GraphicOptions theGraphicOptions; protected CompositionOptions theCompositionOptions; protected PrinterJob thePrinterJob; // documents protected GlycanDocument theStructures; // renderers protected GlycanRenderer theGlycanRenderer; /** Empty constructor. Initialize the dictionaries from the default files and set all the options to their default values. */ public BuilderWorkspace() { super(false); init(); } /** Load the configuration from a file. Initialize the dictionaries from the default files and set all the options to the values stored in the configuration. @param config_file the configuration file @param create if <code>true</code> create a configuration file from the default value in case the file does not exists */ public BuilderWorkspace(String config_file, boolean create) { super(false); init(config_file,create,false); init(); } // base document public int size() { return 1; } public String getName() { return "Workspace"; } public Collection<javax.swing.filechooser.FileFilter> getFileFormats() { return new Vector<javax.swing.filechooser.FileFilter>(); } public javax.swing.filechooser.FileFilter getAllFileFormats() { return null; } public void initData() { init(null,false,true); } // protected void createConfiguration() { theConfiguration = new Configuration(); theFileHistory = new FileHistory(); theResidueHistory = new ResidueHistory(); theMassOptions = new MassOptions(); theGraphicOptions = new GraphicOptions(); theCompositionOptions = new CompositionOptions(); thePrinterJob = null; // printer job is created only the first time is requested // this is because applets needs permission from the user // to print } /** Load the configuration from a file. Initialize the dictionaries from the default files and set all the options to the values stored in the configuration. @param config_file the configuration file @param create if <code>true</code> create a configuration file from the default value in case the file does not exists @param keep_configuration if <code>true</code> the configuration is not reloaded */ public void init(String config_file, boolean create, boolean keep_configuration ) { if( !keep_configuration || theConfiguration==null ) { // create configuration instances createConfiguration(); // initialize configuration if( config_file!=null && theConfiguration.open(config_file) ) retrieveFromConfiguration(); else { storeToConfiguration(true); if( config_file!=null && create ) theConfiguration.save(config_file); } // initialize dictionaries if( !loaded ) { ResidueDictionary.loadDictionary(FileConstants.RESIDUE_TYPES_FILE); TerminalDictionary.loadDictionary(FileConstants.TERMINAL_TYPES_FILE); CoreDictionary.loadDictionary(FileConstants.CORE_TYPES_FILE); CrossRingFragmentDictionary.loadDictionary(FileConstants.CROSS_RING_FRAGMENT_TYPES_FILE); loaded = true; } // initialize style theResiduePlacementDictionary = new ResiduePlacementDictionary(); theResidueStyleDictionary = new ResidueStyleDictionary(); theLinkageStyleDictionary = new LinkageStyleDictionary(); loadStyles(theGraphicOptions.NOTATION); setDisplay(theGraphicOptions.DISPLAY); } // initialize documents theStructures = new GlycanDocument(this); // initialize renderers theGlycanRenderer = new GlycanRenderer(); theGlycanRenderer.setGraphicOptions(theGraphicOptions); theGlycanRenderer.setResiduePlacementDictionary(theResiduePlacementDictionary); theGlycanRenderer.setResidueStyleDictionary(theResidueStyleDictionary); theGlycanRenderer.setLinkageStyleDictionary(theLinkageStyleDictionary); } protected void retrieveFromConfiguration() { theFileHistory.retrieve(theConfiguration); theResidueHistory.retrieve(theConfiguration); theMassOptions.retrieve(theConfiguration); theGraphicOptions.retrieve(theConfiguration); theCompositionOptions.retrieve(theConfiguration); } protected void storeToConfiguration(boolean save_options) { theFileHistory.store(theConfiguration); theResidueHistory.store(theConfiguration); if( save_options ) { theMassOptions.store(theConfiguration); theGraphicOptions.store(theConfiguration); theCompositionOptions.store(theConfiguration); } } /** Store the configuration to a file. If the <code>autosave</code> flag is set all the option values are first stored in the configuration. @param config_file the destination configuration file */ public void exit(String config_file) { if( config_file!=null ) { storeToConfiguration(autosave); theConfiguration.save(config_file); } } /** Return the value of the <code>autosave</code> flag @see #exit(String) */ public boolean getAutoSave() { return autosave; } /** Set the value of the <code>autosave</code> flag @see #exit(String) */ public void setAutoSave(boolean flag) { autosave = flag; } /** Return the configuration object. */ public Configuration getConfiguration() { return theConfiguration; } /** Return the list of recently opened files. */ public FileHistory getFileHistory() { return theFileHistory; } /** Store the file history into the configuration. */ public void storeFileHistory() { theFileHistory.store(theConfiguration); } /** Return the list of recently added residues. */ public ResidueHistory getResidueHistory() { return theResidueHistory; } /** Store the residue history into the configuration. */ public void storeResidueHistory() { theResidueHistory.store(theConfiguration); } /** Return the mass options used when creating new structures. */ public MassOptions getDefaultMassOptions() { return theMassOptions; } /** Set the mass options values. */ public void setDefaultMassOptions(MassOptions mass_opt) { if( mass_opt!=null ) theMassOptions = mass_opt; } /** Store the mass options into the configuration. */ public void storeDefaultMassOptions() { theMassOptions.store(theConfiguration); } /** Return the graphic options used to display structures. */ public GraphicOptions getGraphicOptions() { return theGraphicOptions; } /** Store the graphic options into the configuration. */ public void storeGraphicOptions() { theGraphicOptions.store(theConfiguration); } /** Return the options used to create new glycan compositions. */ public CompositionOptions getCompositionOptions() { return theCompositionOptions; } /** Store the composition options into the configuration. */ public void storeCompositionOptions() { theCompositionOptions.store(theConfiguration); } /** Return a printer job object with the current printing options. Lazily initialize the object if necessary. */ public PrinterJob getPrinterJob() { if( thePrinterJob==null ) { // lazy creation of PrinterJob try { thePrinterJob = PrinterJob.getPrinterJob(); } catch(Exception e) { LogUtils.report(e); } } return thePrinterJob; } /** Return the document containing the glycan structures. */ public GlycanDocument getStructures() { return theStructures; } /** Return the renderer used to create graphic representations of the structures. */ public GlycanRenderer getGlycanRenderer() { return theGlycanRenderer; } /** Set the graphical notation used to represent the glycan structures. Load all style dictionaries with the values corresponding to this notation. @see GraphicOptions#NOTATION */ public void setNotation(String notation) { theGraphicOptions.NOTATION = notation; loadStyles(notation); } /** Set the way structures are display in a specific notation. @see GraphicOptions#DISPLAY */ public void setDisplay(String display) { theGraphicOptions.setDisplay(display); } protected void loadStyles(String notation) { if( notation.equals(GraphicOptions.NOTATION_UOXF) ) { theResiduePlacementDictionary.loadPlacements(FileConstants.RESIDUE_PLACEMENTS_FILE_UOXF); theResidueStyleDictionary.loadStyles(FileConstants.RESIDUE_STYLES_FILE_UOXF); theLinkageStyleDictionary.loadStyles(FileConstants.LINKAGE_STYLES_FILE_UOXF); } else if (notation.equals(GraphicOptions.NOTATION_UOXFCOL) ) { theResiduePlacementDictionary.loadPlacements(FileConstants.RESIDUE_PLACEMENTS_FILE_UOXF); theResidueStyleDictionary.loadStyles(FileConstants.RESIDUE_STYLES_FILE_UOXFCOL); theLinkageStyleDictionary.loadStyles(FileConstants.LINKAGE_STYLES_FILE_UOXF); } else if( notation.equals(GraphicOptions.NOTATION_TEXT) ) { theResiduePlacementDictionary.loadPlacements(FileConstants.RESIDUE_PLACEMENTS_FILE_TEXT); theResidueStyleDictionary.loadStyles(FileConstants.RESIDUE_STYLES_FILE_TEXT); theLinkageStyleDictionary.loadStyles(FileConstants.LINKAGE_STYLES_FILE_TEXT); } else if( notation.equals(GraphicOptions.NOTATION_CFGLINK) ) { theResiduePlacementDictionary.loadPlacements(FileConstants.RESIDUE_PLACEMENTS_FILE_CFGLINK); theResidueStyleDictionary.loadStyles(FileConstants.RESIDUE_STYLES_FILE_CFGLINK); theLinkageStyleDictionary.loadStyles(FileConstants.LINKAGE_STYLES_FILE_CFGLINK); } else if( notation.equals(GraphicOptions.NOTATION_CFGBW) ) { theResiduePlacementDictionary.loadPlacements(FileConstants.RESIDUE_PLACEMENTS_FILE_CFGBW); theResidueStyleDictionary.loadStyles(FileConstants.RESIDUE_STYLES_FILE_CFGBW); theLinkageStyleDictionary.loadStyles(FileConstants.LINKAGE_STYLES_FILE_CFGBW); } else { theResiduePlacementDictionary.loadPlacements(FileConstants.RESIDUE_PLACEMENTS_FILE_CFG); theResidueStyleDictionary.loadStyles(FileConstants.RESIDUE_STYLES_FILE_CFG); theLinkageStyleDictionary.loadStyles(FileConstants.LINKAGE_STYLES_FILE_CFG); } } /** Return all the documents present in this workspace. */ public Collection<BaseDocument> getAllDocuments() { Vector<BaseDocument> ret = new Vector<BaseDocument>(); ret.add(this); ret.add(theStructures); return ret; } /** Return all the documents in the workspace that have been changed since their initialization. */ public Collection<BaseDocument> getUnsavedDocuments() { Vector<BaseDocument> ret = new Vector<BaseDocument>(); if( theStructures.hasChanged() ) ret.add(theStructures); return ret; } /** Reset the change status flags for all the documents. */ public void resetChanges() { this.resetStatus(); theStructures.resetStatus(); fireDocumentInit(); } // listeners public void documentInit(BaseDocument.DocumentChangeEvent e) { // there's a change in some internal document setChanged(true); fireDocumentChanged((BaseDocument)e.getSource()); } public void documentChanged(BaseDocument.DocumentChangeEvent e) { // there's a change in some internal document setChanged(true); fireDocumentChanged((BaseDocument)e.getSource()); } /** Fire a init event for all the documents in the workspace and for the workspace object itself. */ public void fireDocumentInit() { super.fireDocumentInit(); theStructures.fireDocumentInit(); } /** Fire a init event for the given document in the workspace. */ public void fireDocumentInit(BaseDocument source) { if( source==this ) fireDocumentInit(); else super.fireDocumentInit(source); } // serialization /** Create a string representation in XML format of the workspace object containing the configuration and all the documents. */ public String toString() { ByteArrayOutputStream bos = new ByteArrayOutputStream(); Document document = XMLUtils.newDocument(); document.appendChild(toXML(document)); XMLUtils.write(bos,document); return bos.toString(); } /** Parse a string representation in XML format of the workspace object containing the configuration and all the documents. */ public void fromString(String str, boolean merge) throws Exception { ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes()); Document document = XMLUtils.read(bis); if( document==null ) throw new Exception("Cannot read from string"); fromXML(XMLUtils.assertChild(document,"GlycanWorkspace"),merge); } /** Parse an element of a DOM document containing the configuration and all the workspace documents. */ public void fromXML(Node w_node, boolean merge) throws Exception { resetStatus(); // set glycan document Node gd_node = XMLUtils.findChild(w_node,"Structures"); if( gd_node!=null ) theStructures.fromXML(gd_node,merge); } /** Create an element of a DOM document containing the configuration and all the workspace documents. */ public Element toXML(Document document) { if( document==null ) return null; // create root node Element w_node = document.createElement("GlycanWorkspace"); // create configuration node storeToConfiguration(true); w_node.appendChild(theConfiguration.toXML(document)); // create structures node w_node.appendChild(theStructures.toXML(document)); return w_node; } }