Logo Search packages:      
Sourcecode: massxpert version File versions

polChemDef.cpp

/* massXpert - the true massist's program.
   --------------------------------------
   Copyright(C) 2006,2007 Filippo Rusconi

   http://www.massxpert.org/massXpert

   This file is part of the massXpert project.

   The massxpert project is the successor to the "GNU polyxmass"
   project that is an official GNU project package(see
   www.gnu.org). The massXpert project is not endorsed by the GNU
   project, although it is released ---in its entirety--- under the
   GNU General Public License. A huge part of the code in massXpert
   is actually a C++ rewrite of code in GNU polyxmass. As such
   massXpert was started at the Centre National de la Recherche
   Scientifique(FRANCE), that granted me the formal authorization to
   publish it under this Free Software License.

   This software is free software; you can redistribute it and/or
   modify it under the terms of the GNU  General Public
   License version 3, as published by the Free Software Foundation.
   

   This software 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
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this software; if not, write to the

   Free Software Foundation, Inc.,

   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/


/////////////////////// Qt includes
#include <QDebug>


/////////////////////// Local includes
#include "polChemDef.hpp"
#include "monomer.hpp"
#include "polymer.hpp"
#include "modification_default_vignette.hpp"
#include "cross_link_default_vignette.hpp"


namespace massXpert
{

  const int POL_CHEM_DEF_FILE_FORMAT_VERSION = 5;
  
  //! Constructs a polymer chemistry definition.
00056   PolChemDef::PolChemDef()
  {
    //   qDebug() << __FILE__ << __LINE__ 
    //          << "PolChemDef():" << this;

    // We have to set the m_codeLength member to 1. It would make no
    // sense to have monomers described with codes of 0-character
    // length.
    m_codeLength = 1;
    m_refCount = 0;
  
    return;
  }


  //! Constructs a polymer chemistry definition.
  /*! The \p spec argument provides data for the initialization of the
    polymer chemistry definition.
  
    \param spec polymer chemistry definition specification. 
  */
00077   PolChemDef::PolChemDef(const PolChemDefSpec &spec)
  {
    m_name = spec.name();

    //   qDebug() << __FILE__ << __LINE__ 
    //          << "PolChemDef():" << m_name << this;

    m_filePath = spec.filePath();
  
    m_codeLength = 1;
    m_refCount = 0;
    return;
  }

  //! Destroys the polymer chemistry definition
00092   PolChemDef::~PolChemDef()
  {
    //   qDebug() << __FILE__ << __LINE__ 
    //          << "Entering ~PolChemDef():" << m_name << this;
  
    // We have to free all the allocated stuff in the QList members !
    while(!m_atomList.isEmpty())
      delete m_atomList.takeFirst();
  
    while(!m_monomerList.isEmpty())
      delete m_monomerList.takeFirst();

    while(!m_modifList.isEmpty())
      delete m_modifList.takeFirst();

    while(!m_crossLinkerList.isEmpty())
      delete m_crossLinkerList.takeFirst();

    while(!m_cleaveSpecList.isEmpty())
      delete m_cleaveSpecList.takeFirst();

    while(!m_fragSpecList.isEmpty())
      delete m_fragSpecList.takeFirst();

    while(! m_monomerSpecList.isEmpty())
      delete m_monomerSpecList.takeFirst();

    while(! m_modifSpecList.isEmpty())
      delete m_modifSpecList.takeFirst();

    //   qDebug() << __FILE__ << __LINE__ 
    //          << "Leaving ~PolChemDef():" << this;
  }


  //! Sets the name.
  /*!
    \param str New name.
  */
  void 
00132   PolChemDef::setName(const QString &str)
  {
    m_name = str;
  }


  //! Returns the name. 
  /*! 
    \return The name.
  */
  QString
00143   PolChemDef::name() const
  {
    return m_name;
  }


  //! Sets the file path.
  /*!
    \param str New file path.
  */
  void 
00154   PolChemDef::setFilePath(const QString &str)
  {
    m_filePath = str;
  }


  //! Returns the file path. 
  /*! 
    \return The file path.
  */
  QString
00165   PolChemDef::filePath() const
  {
    return m_filePath;
  }


  //! Computes the directory path.
  /*! 
    \return The directory path.
  */
  QString
00176   PolChemDef::dirPath() const
  {
    QFileInfo fileInfo(m_filePath);
    QDir dir(fileInfo.dir());
    return dir.absolutePath();
  }



  //! Sets the left cap formula.
  /*!
    \param formula New formula.
  */
  void 
00190   PolChemDef::setLeftCap(const Formula &formula)
  {
    m_leftCap = formula;
  }


  //! Returns the left cap formula.
  /*! 
    \return The formula.
  */
  const Formula &
00201   PolChemDef::leftCap() const
  {
    return m_leftCap;
  }


  //! Sets the right cap formula.
  /*!
    \param formula New formula.
  */
  void PolChemDef::
00212   setRightCap(const Formula &formula)
  {
    m_rightCap = formula;
  }


  //! Returns the right cap formula.
  /*! 
    \return The formula.
  */
  const Formula &
00223   PolChemDef::rightCap() const
  {
    return m_rightCap;
  }


  //! Sets the code length.
  /*!
    \param value New code length.
  */
  void 
00234   PolChemDef::setCodeLength(int value)
  {
    m_codeLength = value;
  }


  //! Returns the code length.
  /*! 
    \return The code length.
  */
  int 
00245   PolChemDef::codeLength() const
  {
    return m_codeLength;
  }



  void 
  PolChemDef::setRepositoryList(QList<PolChemDef *> *repositoryList)
  {
    Q_ASSERT(repositoryList);
  
    mp_repositoryList = repositoryList;
  }


  //! Constructs a string with all the known monomer codes.
  /*! The string starts with '@' and goes on with all the monomer codes
    separated by the same '@' character. The string is ended with a '@'.
  
    \return always true.
  */
  bool 
00268   PolChemDef::calculateDelimitedCodes()
  {
    // We have to produce a QString containing all the codes from the
    // monomers known to this polymer chemistry definition.
  
    m_delimitedCodes.clear();
    m_delimitedCodes.append('@');

    for (int iter = 0; iter < m_monomerList.size(); ++iter)
      {
      Monomer *monomer = m_monomerList.at(iter);
      Q_ASSERT(monomer);
      
      m_delimitedCodes.append(monomer->code());
      m_delimitedCodes.append('@');
      }

    //  Close the string with a delim char:
    m_delimitedCodes.append('@');

    return true;
  }


  //! Returns the delimited codes string.
  /*! If the string is found to be empty(that is the string has never
    been created), calculateDelimitedCodes() is called first.

    \return The delimited codes string.
  */
  const QString &
00299   PolChemDef::delimitedCodes()
  {
    if (m_delimitedCodes.isEmpty())
      calculateDelimitedCodes();
  
    return m_delimitedCodes;
  }


  //! Sets the ionization rule.
  /*! 
    \param ionizeRule New ionization rule.
  */
  void 
00313   PolChemDef::setIonizeRule(const IonizeRule &ionizeRule)
  {
    m_ionizeRule = ionizeRule;
  }


  //! Returns the ionization rule.
  /*! \return The ionization rule.
   */
  const IonizeRule &
00323   PolChemDef::ionizeRule() const
  {
    return m_ionizeRule;
  }


  //! Returns the ionization rule.
  /*! \return The ionization rule.
   */
  IonizeRule *
00333   PolChemDef::ionizeRulePtr()
  {
    return &m_ionizeRule;
  }


  //! Returns the list of atoms.
  /*! 
    \return The list of atoms.
  */
  const QList<Atom *> &
00344   PolChemDef::atomList() const
  {
    return m_atomList;
  }


  //! Returns the list of atoms.
  /*! 
    \return The list of atoms.
  */
  QList<Atom *> *
00355   PolChemDef::atomListPtr()
  {
    return &m_atomList;
  }


  //! Returns the list of monomers.
  /*! 
    \return The list of monomers.
  */
  const QList<Monomer *> &
00366   PolChemDef::monomerList() const
  {
    return m_monomerList;
  }


  //! Returns the list of monomers.
  /*! 
    \return The list of monomers.
  */
  QList<Monomer *> *
00377   PolChemDef::monomerListPtr()
  {
    return &m_monomerList;
  }


  //! Returns the list of modifications.
  /*! 
    \return The list of modifications.
  */
  const QList<Modif *> &
00388   PolChemDef::modifList() const
  {
    return m_modifList;
  }


  //! Returns the list of modifications.
  /*! 
    \return The list of modifications.
  */
  QList<Modif *> *
00399   PolChemDef::modifListPtr()
  {
    return &m_modifList;
  }


  //! Returns the list of cross-linkers.
  /*! 
    \return The list of cross-linkers.
  */
  const QList<CrossLinker *> &
00410   PolChemDef::crossLinkerList() const
  {
    return m_crossLinkerList;
  }


  //! Returns the list of cross-linkers.
  /*! 
    \return The list of cross-linkers.
  */
  QList<CrossLinker *> *
00421   PolChemDef::crossLinkerListPtr() 
  {
    return &m_crossLinkerList;
  }


  //! Returns the list of cleavage specifications.
  /*! 
    \return The list of cleavage specifications.
  */
  const QList<CleaveSpec *> &
00432   PolChemDef::cleaveSpecList() const
  {
    return m_cleaveSpecList;
  }


  //! Returns the list of cleavage specifications.
  /*! 
    \return The list of cleavage specifications.
  */
  QList<CleaveSpec *> *
00443   PolChemDef::cleaveSpecListPtr()
  {
    return &m_cleaveSpecList;
  }


  //! Returns the list of fragmentation specifications.
  /*! 
    \return The list of fragmentation specifications.
  */
  const QList<FragSpec *> &
00454   PolChemDef::fragSpecList() const
  {
    return m_fragSpecList;
  }
  

  //! Returns the list of fragmentation specifications.
  /*! 
    \return The list of fragmentation specifications.
  */
  QList<FragSpec *> *
00465   PolChemDef::fragSpecListPtr() 
  {
    return &m_fragSpecList;
  }
  

  //! Returns the modification object corresponding to name.
  /*!  \param name name of the modification to be searched for. Can be
    empty, in which case the function returns false.

    \param modification if non 0, pointer in which to store the address
    of the found modification. Set to point to the found modification,
    otherwise left unchanged. Can be 0 in which case nothing happens.

    \return true if the modif was found, false otherwise.
  */
  bool
00482   PolChemDef::modif(const QString &name, Modif *modification) const
  {
    if (name.isEmpty())
      return false;
        
    for (int iter = 0; iter < m_modifList.size(); ++iter)
      {
      Modif *modif = m_modifList.at(iter);
      
      if(modif->name() == name)
        {
          if (modification)
            {
            modif->clone(modification);
            
            return true;
            }

          return true;
        }
      }
  
    return false;
  }

  

  bool
  PolChemDef::crossLinker(const QString &name, CrossLinker *crossLinker) const
  {
    if (name.isEmpty())
      return false;
        
    for (int iter = 0; iter < m_crossLinkerList.size(); ++iter)
      {
      CrossLinker *localCrossLinker = m_crossLinkerList.at(iter);
      
      if(localCrossLinker->name() == name)
        {
          if (crossLinker)
            {
            localCrossLinker->clone(crossLinker);
            
            return true;
            }

          return true;
        }
      }
  
    return false;
  }

  

  //! Returns the hash of vignette renderers.
  /*! 
    \return The hash of vignette renderers.
  */
  QHash<QString, ChemEntVignetteRenderer *> * 
00542   PolChemDef::chemEntVignetteRendererHash()
  {
    return &m_chemEntVignetteRendererHash;
  }


  //! Searches a chemical entity vignette renderer associated to \p key.
  /*! Searches in the chemical entity vignette renderers' hash for a
    vignette renderer having a key \p key.
  
    \param key Key with which to look for a vignette renderer.

    \return The vignette renderer associated to \p key.
  */
  ChemEntVignetteRenderer * 
00557   PolChemDef::chemEntVignetteRenderer(const QString &key)
  {
    return m_chemEntVignetteRendererHash.value(key);
  }


  //! Creates a chemical entity vignette renderer.
  /*!  The returned renderer must either be set as a shared renderer by
    a ChemEntVignette instance(which takes care of adding a
    reference count to it) or must be dealt with properly so as to avoid
    leaks.
  
    \param filePath File path to the graphics file.

    \param parent Parent object.

    \return The newly allocated chemical entity vignette renderer.

    \sa newMonomerVignetteRenderer(const QString &code, QObject *parent).
    \sa newModifVignetteRenderer(const QString &name, QObject *parent).
  */
  ChemEntVignetteRenderer * 
00579   PolChemDef::newChemEntVignetteRenderer(const QString &filePath,
                                QObject *parent)
  {
    return new ChemEntVignetteRenderer(filePath, parent);
  }


  //! Creates a monomer vignette renderer.
  /*! 
  
    \param str Code of the monomer.

    \param parent Parent object.

    \return The newly allocated monomer vignette renderer or 0 upon
    failure.

    \sa newModifVignetteRenderer(const QString &str, QObject *parent).
  */
  ChemEntVignetteRenderer * 
00599   PolChemDef::newMonomerVignetteRenderer(const QString &str,
                                QObject *parent)
  {
    MonomerSpec *monomerSpec = 0;
    bool found = false;
    
    for (int iter = 0; iter < m_monomerSpecList.size(); ++iter)
      {
      monomerSpec = m_monomerSpecList.at(iter);
      
      if(monomerSpec->code() == str)
        {
          found = true;
          break;
        }
      }
  
    if (!found)
      return(0);
  
    QString filePath = dirPath() + QDir::separator() + monomerSpec->vector();
  
    ChemEntVignetteRenderer *chemEntVignetteRenderer = 
      new ChemEntVignetteRenderer(filePath, parent);
  
    if (!chemEntVignetteRenderer->isValid())
      {
      delete chemEntVignetteRenderer;
      return 0;
      }
  
    m_chemEntVignetteRendererHash.insert(monomerSpec->code(),
                                chemEntVignetteRenderer);
  
    chemEntVignetteRenderer->setHash(&m_chemEntVignetteRendererHash);
  
    return chemEntVignetteRenderer;
  }


  //! Creates a modification vignette renderer.
  /*! 
  
    \param str Name.

    \param parent Parent object.

    \return The newly allocated modification vignette renderer or 0 upon
    failure.

    \sa newMonomerVignetteRenderer(const QString &str, QObject *parent).
  */
  ChemEntVignetteRenderer * 
00652   PolChemDef::newModifVignetteRenderer(const QString &modifName,
                              QObject *parent)
  {
    ModifSpec *modifSpec = 0;
    bool found = false;
    
    for (int iter = 0; iter < m_modifSpecList.size(); ++iter)
      {
      modifSpec = m_modifSpecList.at(iter);
      
      if(modifSpec->name() == modifName)
        {
          found = true;
          break;
        }
      }
  
    // If the modification name modifName is for a modification that has no
    // vignette associated to it in modification_dictionary, then use
    // the default one(if there is one in the directory corresponding
    // to current polymer chemistry definition). If there is not any,
    // then use the one that is defined in the
    // modification_default_vignette.hpp file included in this source
    // file.

    QString filePath;
  
    if (!found)
      filePath = dirPath() + QDir::separator() + "default-modif-vignette.svg";
    else
      filePath = dirPath() + QDir::separator() + modifSpec->vector();
  
    ChemEntVignetteRenderer *chemEntVignetteRenderer = 0;
  
    if (!QFile(filePath).exists())
      {
      // None of the two files exists. Try to construct the renderer
      // using the svg vignette declared in
      // modification_default_vignette.hpp in the form of QByteArray
      // defaultModifVignette.
      chemEntVignetteRenderer =
        new ChemEntVignetteRenderer(defaultModifVignette, parent);
      }
    else
      {
      chemEntVignetteRenderer =
        new ChemEntVignetteRenderer(filePath, parent);
      }
  
    if (!chemEntVignetteRenderer->isValid())
      {
      if(chemEntVignetteRenderer)
        delete chemEntVignetteRenderer;
      
      return 0;
      }
  
    m_chemEntVignetteRendererHash.insert(modifName, chemEntVignetteRenderer);
 
    chemEntVignetteRenderer->setHash(&m_chemEntVignetteRendererHash);
  
    return chemEntVignetteRenderer;
  }



  ChemEntVignetteRenderer * 
  PolChemDef::newCrossLinkerVignetteRenderer(const QString &name,
                                    QObject *parent)
  {
    CrossLinkerSpec *crossLinkerSpec = 0;
    bool found = false;
  
    for (int iter = 0; iter < m_crossLinkerSpecList.size(); ++iter)
      {
      crossLinkerSpec = m_crossLinkerSpecList.at(iter);
      
      if(crossLinkerSpec->name() == name)
        {
          found = true;
          break;
        }
      }
  
    // If the crossLinker name is for a crossLink that has no
    // vignette associated to it in cross_linker_dictionary, then use
    // the default one(if there is one in the directory corresponding
    // to current polymer chemistry definition). If there is not any,
    // then use the one that is defined in the
    // modification_default_vignette.hpp file included in this source
    // file.

    QString filePath;
  
    if (!found)
      filePath = 
      dirPath() + QDir::separator() + "default-cross-link-vignette.svg";
    else
      filePath = 
      dirPath() + QDir::separator() + crossLinkerSpec->vector();
  
    ChemEntVignetteRenderer *chemEntVignetteRenderer = 0;
  
    if (!QFile(filePath).exists())
      {
      // None of the two files exists. Try to construct the renderer
      // using the svg vignette declared in
      // cross_link_default_vignette.hpp in the form of QByteArray
      // defaultModifVignette.
      chemEntVignetteRenderer =
        new ChemEntVignetteRenderer(defaultCrossLinkerVignette, parent);
      }
    else
      {
      chemEntVignetteRenderer =
        new ChemEntVignetteRenderer(filePath, parent);
      }
  
    if (!chemEntVignetteRenderer->isValid())
      {
      if(chemEntVignetteRenderer)
        delete chemEntVignetteRenderer;
      
      return 0;
      }
  
    m_chemEntVignetteRendererHash.insert(name, chemEntVignetteRenderer);
 
    chemEntVignetteRenderer->setHash(&m_chemEntVignetteRendererHash);
  
    return chemEntVignetteRenderer;
  }



  //! Sets the reference count.
  /*! Sets the number of times this polymer chemistry definition is in
    use.
  
    \param refCount New reference count.
  */
  void 
00794   PolChemDef::setRefCount(int refCount)
  {
    m_refCount = refCount;
  }


  //! Returns the reference count.
  /*! Returns the number of times that this polymer chemistry definition
    is in use.
  
    \return The reference count.
  */
  int 
00807   PolChemDef::refCount()
  {
    return m_refCount;
  }


  //! Increments the reference count by one unit.
  void 
00815   PolChemDef::incrementRefCount()
  {
    ++m_refCount;

    //   qDebug() << __FILE__ << __LINE__ 
    //          << "incrementRefCount() to:" << m_refCount << m_name << this;
  }


  //! Decrements the reference count by one unit.
  void 
00826   PolChemDef::decrementRefCount()
  {
    --m_refCount;
  
//       qDebug() << __FILE__ << __LINE__ 
//              << "decrementRefCount() to:" << m_refCount << m_name << this;

    if (!m_refCount)
      {
      // The count has come down to zero, remove this definition from
      // its repository list.

      if(mp_repositoryList)
        {
//        qDebug() << __FILE__ << __LINE__ 
//                << "Going to remove  this from repository:" 
//                << m_name << this;
          
          int res = mp_repositoryList->removeAll(this);
          
          if (!res)
            qFatal("Fatal error at %s@%d. Program aborted.",
                  __FILE__, __LINE__);
        }
      
//    qDebug() << __FILE__ << __LINE__ 
//            << "Going to 'delete  this':" << m_name << this;

      delete this;
      }
  }
  

  //! Returns the list of monomer specifications.
  /*!  \return The list.
   */
  QList<MonomerSpec *> *
00863   PolChemDef::monomerSpecList()
  {
    return &m_monomerSpecList;
  }


  //! Returns the list of modification specifications.
  /*!  \return The list.
   */
  QList<ModifSpec *> *
00873   PolChemDef::modifSpecList()
  {
    return &m_modifSpecList;
  }


  //! Returns the list of cross-link specifications.
  /*!  \return The list.
   */
  QList<CrossLinkerSpec *> *
00883   PolChemDef::crossLinkerSpecList()
  {
    return &m_crossLinkerSpecList;
  }



  //! Parses a polymer chemistry definition file.
  /*! Parses the polymer chemistry definition data XML file. Updates the
    member data according to all the child elements parsed.
  
    \return true if parsing was successful, false otherwise.
  */
  bool 
00897   PolChemDef::renderXmlPolChemDefFile()
  {
    QDomDocument doc("polChemDefData");
    QDomElement element;  
    QDomElement child;
    QDomElement indentedChild;
  
    QFile file(m_filePath);
  
    Atom *atom = 0;
    Monomer *monomer = 0;
    Modif *modif = 0;
    CrossLinker *crossLinker = 0;
    CleaveSpec *cleaveSpec = 0;
    FragSpec *fragSpec = 0;
  
  
    // The general structure of the file we are reading is this:
    //
    // <polchemdefinition>
    // <atomdefdata>
    //   <atom>
    //     <name>Hydrogen</name>
    //     <symbol>H</symbol>
    //     <isotope>
    //       <mass>1.0078250370</mass>
    //       <abund>99.9885000000</abund>
    //     </isotope>
    //     <isotope>
    //       <mass>2.0141017870</mass>
    //       <abund>0.0115000000</abund>
    //     </isotope>
    //   </atom>
    // ...
    // </atomdefdata>
    // <polchemdefdata version="0.1">        
    //   <name>protein</name>          
    //   <leftcap>+H</leftcap>               
    //   <rightcap>+OH</rightcap>      
    //   <codelen>1</codelen>          
    //   <ionizerule>                  
    //     <formula>+H</formula>       
    //     <charge>1</charge>          
    //     <level>1</level>            
    //   </ionizerule>                 
    //   <monomers>                    
    //     <mnm>                 
    //       <name>Glycine</name>      
    //       <code>G</code>            
    //       <formula>C2H3NO</formula>       
    //     </mnm>
    //   </monomers>
    //   <modifs>                   
    //     <mdf>                    
    //       <name>Phosphorylation</name>    
    //       <formula>-H+H2PO3</formula>     
    //     </mdf>
    //   </modifs>      
    //   <cleavespecs>                       
    //     <cls>                       
    //       <name>CyanogenBromide</name>    
    //       <pattern>M/</pattern>           
    //       <clr>                           
    //         <re-mnm-code>M</re-mnm-code>        
    //         <re-formula>-CH2S+O</re-formula>   
    //       </clr>                          
    //     </cls>
    //  </cleavespecs>
    //   <fragspecs>                      
    //     <fgs>                    
    //       <name>a</name>               
    //       <end>LE</end>                
    //       <formula>-C1O1</formula>           
    //       <fgr>                        
    //         <name>a-fgr-1</name>       
    //         <formula>+H200</formula>   
    //         <prev-mnm-code>E</prev-mnm-code>
    //         <this-mnm-code>D</this-mnm-code>
    //         <next-mnm-code>F</next-mnm-code>
    //         <comment>comment here!</comment>
    //       </fgr>
    //     </fgs>
    //  </fragspecs>
    // </polchemdefdata>
    // </polchemdefinition>

    if (!file.open(QIODevice::ReadOnly))
      return false;
  
    if (!doc.setContent(&file)) 
      {
      file.close();
      return false;
      }
  
    file.close();

    element = doc.documentElement();

    if (element.tagName() != "polchemdefinition")
      {
      qDebug() << __FILE__ << __LINE__
              << "Polymer chemistry definition file is erroneous\n";
      return false;
      }
  
    ///////////////////////////////////////////////
    // Check the version of the document.
  
    QString text;
  
    if (!element.hasAttribute("version"))
      text = "1";
    else
      text = element.attribute("version");
  
    bool ok = false;
  
    int version = text.toInt(&ok, 10);

    if (version < 1 || !ok)
      {
      qDebug() << __FILE__ << __LINE__
              << "Polymer chemistry definition file has bad "
        "version number:"
              << version;

      return false;
      }
  

    //////////////////////////////////////////////
    // <atom data>

    child = element.firstChildElement();
    if (child.tagName() != "atomdefdata")
      {
      qDebug() << __FILE__ << __LINE__
              << "Polymer chemistry definition file is erroneous\n";
      return false;
      }
  
    indentedChild = child.firstChildElement();
    while(!indentedChild.isNull())
      {
      if(indentedChild.tagName() != "atom")
        return false;
      
      atom = new Atom();
      
      if(!atom->renderXmlAtomElement(indentedChild, version))
        {
          delete atom;
          return false;
        }
     
      m_atomList.append(atom);

      indentedChild = indentedChild.nextSiblingElement();
      }
  

    //////////////////////////////////////////////
    // <polymer chemistry data>

    child = child.nextSiblingElement();
    if (child.tagName() != "polchemdefdata")
      {
      qDebug() << __FILE__ << __LINE__
              << "Polymer chemistry definition file is erroneous\n";
      return false;
      }
  
    // <name>
    child = child.firstChildElement();
    if (child.tagName() != "name")
      return false;
    m_name = child.text();
  
    // <leftcap>
    child = child.nextSiblingElement();
    if (child.tagName() != "leftcap")
      return false;
    m_leftCap.setFormula(child.text());

    // <rightcap>
    child = child.nextSiblingElement();
    if (child.tagName() != "rightcap")
      return false;
    m_rightCap.setFormula(child.text());
   
    // <codelen>
    child = child.nextSiblingElement();
    if (child.tagName() != "codelen")
      return false;
    ok = false;
    m_codeLength = child.text().toInt(&ok);
    if (m_codeLength == 0 && !ok)
      return false;
  
    // <ionizerule>
    child = child.nextSiblingElement();
    if (child.tagName() != "ionizerule")
      return false;
    if (!m_ionizeRule.renderXmlIonizeRuleElement(child))
      return false;
    // We have to ascertain that the IonizeRule is valid.
    if (!m_ionizeRule.validate(m_atomList))
      return false;
    
    // <monomers>
    child = child.nextSiblingElement();
    if (child.tagName() != "monomers")
      return false;
  
    indentedChild = child.firstChildElement();
    while(!indentedChild.isNull())
      {
      if(indentedChild.tagName() != "mnm")
        return false;
      
      monomer = new Monomer(this, "NOT_SET");

      if(!monomer->renderXmlMnmElement(indentedChild, version))
        {
          delete monomer;
          return false;
        }

      m_monomerList.append(monomer);
      
      indentedChild = indentedChild.nextSiblingElement();
      }
  
    // <modifs>
    child = child.nextSiblingElement();
    if (child.tagName() != "modifs")
      return false;
  
    indentedChild = child.firstChildElement();
    while(!indentedChild.isNull())
      {
      if(indentedChild.tagName() != "mdf")
        return false;
      
      modif = new Modif(this, "NOT_SET");
      
      if(!modif->renderXmlMdfElement(indentedChild, version))
        {
          delete modif;
          return false;
        }
      
      m_modifList.append(modif);
      
      indentedChild = indentedChild.nextSiblingElement();
      }
  
    // <crosslinkers>

    // Note that crosslinkers have appeared since version 3.

    if (version > 2)
      {
      child = child.nextSiblingElement();
      if(child.tagName() != "crosslinkers")
        return false;
      
      indentedChild = child.firstChildElement();
      while(!indentedChild.isNull())
        {
          if (indentedChild.tagName() != "clk")
            return false;
        
          crossLinker = new CrossLinker(this, 
                                 "NOT_SET", "NOT_SET");
        
          if (!crossLinker->renderXmlClkElement(indentedChild, version))
            {
            delete crossLinker;
            return false;
            }
        
          m_crossLinkerList.append(crossLinker);
        
          indentedChild = indentedChild.nextSiblingElement();
        }
      }
  
    // <cleavespecs>
    child = child.nextSiblingElement();
    if (child.tagName() != "cleavespecs")
      return false;
  
    indentedChild = child.firstChildElement();
    while(!indentedChild.isNull())
      {
      if(indentedChild.tagName() != "cls")
        return false;
      
      cleaveSpec = new CleaveSpec(this, "NOT_SET");
      
      if(!cleaveSpec->renderXmlClsElement(indentedChild, version))
        {
          delete cleaveSpec;
          return false;
        }

      m_cleaveSpecList.append(cleaveSpec);
    
      indentedChild = indentedChild.nextSiblingElement();
      }

    // <fragspecs>
    child = child.nextSiblingElement();
    if (child.tagName() != "fragspecs")
      return false;
  
    indentedChild = child.firstChildElement();
    while(!indentedChild.isNull())
      {
      if(indentedChild.tagName() != "fgs")
        return false;
      
      fragSpec = new FragSpec(this, "NOT_SET");
      
      if(!fragSpec->renderXmlFgsElement(indentedChild, version))
        {
          delete fragSpec;
          return false;
        }
  
      m_fragSpecList.append(fragSpec);
      
      indentedChild = indentedChild.nextSiblingElement();
      }
  
    return true;
  }

  
  //! Creates the XML DTD for a polymer chemistry definition file.
  /*! \return The DTD in string format.
   */
  QString *
01242   PolChemDef::formatXmlDtd()
  {
    QString *string = new QString 
     (
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
       "<!-- DTD for polymer definitions, used by the\n"
       "'massXpert' mass spectrometry application.\n"
       "Copyright 2006,2007,2008 Filippo Rusconi\n"
       "Licensed under the GNU GPL -->\n"
       "<!DOCTYPE polchemdefinition [\n"
       "<!ELEMENT polchemdefinition (atomdefdata,polchemdefdata)>\n"
       "<!ATTLIST polchemdefinition version NMTOKEN #REQUIRED>\n"
       "<!ELEMENT atomdefdata (atom+)>\n"
       "<!ELEMENT atom (name,symbol,isotope+)>\n"
       "<!ELEMENT symbol (#PCDATA)>\n"
       "<!ELEMENT isotope (mass , abund)>\n"
       "<!ELEMENT mass (#PCDATA)>\n"
       "<!ELEMENT abund (#PCDATA)>\n"
       "<!ELEMENT polchemdefdata (name,leftcap,rightcap,codelen,ionizerule,monomers,modifs,crosslinkers,cleavespecs,fragspecs)>\n"
       "<!ELEMENT ionizerule (formula,charge,level)>\n"
       "<!ELEMENT monomers (mnm*)>\n"
       "<!ELEMENT modifs (mdf*)>\n"
       "<!ELEMENT crosslinkers (clk*)>\n"
       "<!ELEMENT cleavespecs (cls*)>\n"
       "<!ELEMENT fragspecs (fgs*)>\n"
       "<!ELEMENT mnm (name,code,formula)>\n"
       "<!ELEMENT mdf (name,formula,targets,maxcount)>\n"
       "<!ELEMENT clk (name,formula,modifname*)>\n"
       "<!ELEMENT cls (name,pattern,clr*)>\n"
       "<!ELEMENT fgs (name,end,formula,sidechaincontrib,comment?,fgr*)>\n"
       "<!ELEMENT clr (name,(le-mnm-code,le-formula)?,(re-mnm-code,re-formula)?)>\n"
       "<!ELEMENT fgr (name,formula,prev-mnm-code?,curr-mnm-code?,next-mnm-code?,comment?)>\n"
       "<!ELEMENT leftcap (#PCDATA)>\n"
       "<!ELEMENT rightcap (#PCDATA)>\n"
       "<!ELEMENT codelen (#PCDATA)>\n"
       "<!ELEMENT charge (#PCDATA)>\n"
       "<!ELEMENT maxcount (#PCDATA)>\n"
       "<!ELEMENT level (#PCDATA)>\n"
       "<!ELEMENT name (#PCDATA)>\n"
       "<!ELEMENT modifname (#PCDATA)>\n"
       "<!ELEMENT code (#PCDATA)>\n"
       "<!ELEMENT formula (#PCDATA)>\n"
       "<!ELEMENT sidechaincontrib (#PCDATA)>\n"
       "<!ELEMENT targets (#PCDATA)>\n"
       "<!ELEMENT pattern (#PCDATA)>\n"
       "<!ELEMENT end (#PCDATA)>\n"
       "<!ELEMENT le-mnm-code (#PCDATA)>\n"
       "<!ELEMENT re-mnm-code (#PCDATA)>\n"
       "<!ELEMENT le-formula (#PCDATA)>\n"
       "<!ELEMENT re-formula (#PCDATA)>\n"
       "<!ELEMENT comment (#PCDATA)>\n"
       "<!ELEMENT prev-mnm-code (#PCDATA)>\n"
       "<!ELEMENT curr-mnm-code (#PCDATA)>\n"
       "<!ELEMENT next-mnm-code (#PCDATA)>\n"
       "]>\n"
       );
  
    return string;
  }


  //! Write the polymer chemistry definition to file.
  /*!  \return true if successful, false otherwise.
   */
  bool
01307   PolChemDef::writeXmlFile()
  {
    QString *string = 0;
    QString indent("  ");
    QString lead;

    int offset = 0;
    int iter = 0;
  
    // We are asked to send an xml description of the polymer chemistry
    // definition.

    QFile file(m_filePath);
  
    if (!file.open(QIODevice::WriteOnly))
      {
      qDebug() << __FILE__ << __LINE__
              << "Failed to open file" << m_filePath
              << "for writing.";
      
      return false;
      }

    QTextStream stream(&file);
    stream.setCodec("UTF-8");
  
    // The DTD
    string =   formatXmlDtd();
    stream << *string;
    delete string;


    // Open the <polchemdefinition> element.
    stream << QString("<polchemdefinition version=\"%1\">\n")
      .arg(POL_CHEM_DEF_FILE_FORMAT_VERSION);

    // Prepare the lead.
    ++offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }
  
    // Open the <atomdefdata> element.
    stream << QString("%1<atomdefdata>\n")
      .arg(lead);

    // Prepare the lead.
    ++offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }
  
    // All the atoms in the List.
    for (iter = 0; iter < m_atomList.size(); ++iter)
      {
      string = m_atomList.at(iter)->formatXmlAtomElement(2);
      stream << *string;
      delete string;
      }
  
    // Prepare the lead.
    --offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }

    // Close the <atomdefdata> element.
    stream << QString("%1</atomdefdata>\n")
      .arg(lead);
  
    // Open the <polchemdefdata> element.
    stream << QString("%1<polchemdefdata>\n")
      .arg(lead);

    // Prepare the lead.
    ++offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }

    stream << QString("%1<name>%2</name>\n")
      .arg(lead).arg(m_name);
  
    stream << QString("%1<leftcap>%2</leftcap>\n")
      .arg(lead).arg(m_leftCap.formula());
  
    stream << QString("%1<rightcap>%2</rightcap>\n")
      .arg(lead).arg(m_rightCap.formula());
  
    stream << QString("%1<codelen>%2</codelen>\n")
      .arg(lead).arg(m_codeLength);
  
    // Before writing the ionization rule, set the level to 1. This
    // member datum is set to 0 in the constructor.
    m_ionizeRule.setLevel(1);
    string = m_ionizeRule.formatXmlIonizeRuleElement(offset);
    stream << *string;
    delete string;
  
    stream << QString("%1<monomers>\n")
      .arg(lead);

    // Prepare the lead.
    ++offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }

    for (iter = 0 ; iter < m_monomerList.size(); ++iter)
      {
      QString *newString =
        m_monomerList.at(iter)->formatXmlMnmElement(offset);

      stream << *newString;

      delete newString;
      }

    // Prepare the lead.
    --offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }

    stream << QString("%1</monomers>\n")
      .arg(lead);
  

    stream << QString("%1<modifs>\n")
      .arg(lead);

    // Prepare the lead.
    ++offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }

    for (iter = 0 ; iter < m_modifList.size(); ++iter)
      {
      QString *newString = m_modifList.at(iter)->formatXmlMdfElement(offset);

      stream << *newString;

      delete newString;
      }

    // Prepare the lead.
    --offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }

    stream << QString("%1</modifs>\n")
      .arg(lead);
  

    stream << QString("%1<crosslinkers>\n")
      .arg(lead);

    // Prepare the lead.
    ++offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }

    for (iter = 0 ; iter < m_crossLinkerList.size(); ++iter)
      {
      QString *newString = 
        m_crossLinkerList.at(iter)->formatXmlClkElement(offset);

      stream << *newString;

      delete newString;
      }

    // Prepare the lead.
    --offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }

    stream << QString("%1</crosslinkers>\n")
      .arg(lead);


    stream << QString("%1<cleavespecs>\n")
      .arg(lead);

    // Prepare the lead.
    ++offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }

    for (int iter = 0 ; iter < m_cleaveSpecList.size(); ++iter)
      {
      QString *newString = 
        m_cleaveSpecList.at(iter)->formatXmlClsElement(offset);

      stream << *newString;

      delete newString;
      }

    // Prepare the lead.
    --offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }

    stream << QString("%1</cleavespecs>\n")
      .arg(lead);
    

    stream << QString("%1<fragspecs>\n")
      .arg(lead);


    // Prepare the lead.
    ++offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }

    for (int iter = 0 ; iter < m_fragSpecList.size(); ++iter)
      {
      QString *newString = 
        m_fragSpecList.at(iter)->formatXmlFgsElement(offset);

      stream << *newString;

      delete newString;
      }

    // Prepare the lead.
    --offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }

    stream << QString("%1</fragspecs>\n")
      .arg(lead);
  
    // Prepare the lead.
    --offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }

    stream << QString("%1</polchemdefdata>\n")
      .arg(lead);
  
    // Prepare the lead.
    --offset;  
    lead.clear();
    iter = 0;
    while(iter < offset)
      {
      lead += indent;
      ++iter;
      }

    stream << QString("%1</polchemdefinition>\n")
      .arg(lead);
  
    file.close();

    return true;
  }

} // namespace massXpert

Generated by  Doxygen 1.6.0   Back to index