context: /* Copyright (C) 1997-2007  Egon Willighagen <egonw@users.sf.net>
   *
   * Contact: cdk-devel@lists.sourceforge.net
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public License
   * as published by the Free Software Foundation; either version 2.1
   * of the License, or (at your option) any later version.
   * All we ask is that proper credit is given for our work, which includes
   * - but is not limited to - adding the above copyright notice to the beginning
   * of your source code files, and to any copyright notice that you may distribute
   * with programs based on this work.
   *
   * 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.
   *
   * You should have received a copy of the GNU Lesser General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   */
  
  using NCDK.Common.Primitives;
  using NCDK.Dict;
  using NCDK.Geometries;
  using NCDK.Numerics;
  using NCDK.Stereo;
  using NCDK.Tools;
  using NCDK.Tools.Manipulator;
  using System;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.Globalization;
  using System.Linq;
  using System.Xml.Linq;
  
  namespace NCDK.IO.CML
  {
      /// <summary>
      /// Core CML 1.x and 2.x elements are parsed by this class (see <token>cdk-cite-WIL01</token>).
      ///
      /// <para>Please file a bug report if this parser fails to parse
      /// a certain element or attribute value in a valid CML document.</para>
      /// </summary>
      // @cdk.module io
      // @author Egon Willighagen <egonw@sci.kun.nl>
      public class CMLCoreModule : ICMLModule
      {
          protected const string SYSTEMID = "CML-1999-05-15";
  
          // data model to store things into
          protected IChemFile CurrentChemFile { get; set; }
  
          protected IAtomContainer CurrentMolecule { get; set; }
          protected IChemObjectSet<IAtomContainer> CurrentMoleculeSet { get; set; }
          protected IChemModel CurrentChemModel { get; set; }
          protected IChemSequence CurrentChemSequence { get; set; }
          protected IReactionSet CurrentReactionSet { get; set; }
          protected IReaction CurrentReaction { get; set; }
          protected IAtom CurrentAtom { get; set; }
          protected IBond CurrentBond { get; set; }
          protected IStrand CurrentStrand { get; set; }
          protected IMonomer CurrentMonomer { get; set; }
          protected Dictionary<string, IAtom> AtomEnumeration { get; set; }
          protected IList<string> MoleculeCustomProperty { get; set; }
  
          // helper fields
          protected int FormulaCounter { get; set; }
          protected int AtomCounter { get; set; }
          protected List<string> ElSym { get; set; }
          protected List<string> ElTitles { get; set; }
          protected List<string> ElId { get; set; }
          protected List<string> Formula { get; set; }
          protected List<string> FormalCharges { get; set; }
          protected List<string> PartialCharges { get; set; }
          protected List<string> Isotope { get; set; }
          protected List<string> AtomicNumbers { get; set; }
          protected List<string> ExactMasses { get; set; }
          protected List<string> X3 { get; set; }
          protected List<string> Y3 { get; set; }
          protected List<string> Z3 { get; set; }
          protected List<string> X2 { get; set; }
          protected List<string> Y2 { get; set; }
          protected List<string> XFract { get; set; }
          protected List<string> YFract { get; set; }
          protected List<string> ZFract { get; set; }
          protected List<string> HCounts { get; set; }
          protected List<string> AtomParities { get; set; }
          protected List<string> ParityARef1 { get; set; }
          protected List<string> ParityARef2 { get; set; }
          protected List<string> ParityARef3 { get; set; }
          protected List<string> ParityARef4 { get; set; }
          protected List<string> AtomDictRefs { get; set; }
          protected List<string> AtomAromaticities { get; set; }
          protected List<string> SpinMultiplicities { get; set; }
          protected List<string> Occupancies { get; set; }
          protected Dictionary<int, List<string>> AtomCustomProperty { get; set; }
          protected bool ParityAtomsGiven { get; set; }
          protected bool ParityGiven { get; set; }
  
          protected int BondCounter { get; set; }
          protected List<string> BondId { get; set; }
          protected List<string> BondARef1 { get; set; }
          protected List<string> BondARef2 { get; set; }
          protected List<string> Order { get; set; }
          protected List<string> BondStereo { get; set; }
          protected List<string> BondDictRefs { get; set; }
          protected List<string> BondElId { get; set; }
          protected List<bool?> BondAromaticity { get; set; }
          protected Dictionary<string, Dictionary<string, string>> BondCustomProperty { get; set; }
          protected bool StereoGiven { get; set; }
          protected string InChIString { get; set; }
          protected int CurRef { get; set; }
          protected int CurrentElement { get; set; }
          protected string Builtin { get; set; }
          protected string DictRef { get; set; }
          protected string ElementTitle { get; set; }
  
          protected double[] UnitCellParams { get; set; }
          protected int CrystalScalar { get; set; }
  
          public CMLCoreModule(IChemFile chemFile)
          {
              this.CurrentChemFile = chemFile;
          }
  
          public CMLCoreModule(ICMLModule conv)
          {
              Inherit(conv);
          }
  
          public void Inherit(ICMLModule convention)
          {
              if (convention is CMLCoreModule conv)
              {
                  // copy the data model
                  this.CurrentChemFile = conv.CurrentChemFile;
                  this.CurrentMolecule = conv.CurrentMolecule;
                  this.CurrentMoleculeSet = conv.CurrentMoleculeSet;
                  this.CurrentChemModel = conv.CurrentChemModel;
                  this.CurrentChemSequence = conv.CurrentChemSequence;
                  this.CurrentReactionSet = conv.CurrentReactionSet;
                  this.CurrentReaction = conv.CurrentReaction;
                  this.CurrentAtom = conv.CurrentAtom;
                  this.CurrentStrand = conv.CurrentStrand;
                  this.CurrentMonomer = conv.CurrentMonomer;
                  this.AtomEnumeration = conv.AtomEnumeration;
                  this.MoleculeCustomProperty = conv.MoleculeCustomProperty;
  
                  // copy the intermediate fields
                  this.Builtin = conv.Builtin;
                  this.AtomCounter = conv.AtomCounter;
                  this.FormulaCounter = conv.FormulaCounter;
                  this.ElSym = conv.ElSym;
                  this.ElTitles = conv.ElTitles;
                  this.ElId = conv.ElId;
                  this.FormalCharges = conv.FormalCharges;
                  this.PartialCharges = conv.PartialCharges;
                  this.Isotope = conv.Isotope;
                  this.AtomicNumbers = conv.AtomicNumbers;
                  this.ExactMasses = conv.ExactMasses;
                  this.X3 = conv.X3;
                  this.Y3 = conv.Y3;
                  this.Z3 = conv.Z3;
                  this.X2 = conv.X2;
                  this.Y2 = conv.Y2;
                  this.XFract = conv.XFract;
                  this.YFract = conv.YFract;
                  this.ZFract = conv.ZFract;
                  this.HCounts = conv.HCounts;
                  this.AtomParities = conv.AtomParities;
                  this.ParityARef1 = conv.ParityARef1;
                  this.ParityARef2 = conv.ParityARef2;
                  this.ParityARef3 = conv.ParityARef3;
                  this.ParityARef4 = conv.ParityARef4;
                  this.AtomDictRefs = conv.AtomDictRefs;
                  this.AtomAromaticities = conv.AtomAromaticities;
                  this.SpinMultiplicities = conv.SpinMultiplicities;
                  this.Occupancies = conv.Occupancies;
                  this.BondCounter = conv.BondCounter;
                  this.BondId = conv.BondId;
                  this.BondARef1 = conv.BondARef1;
                  this.BondARef2 = conv.BondARef2;
                  this.Order = conv.Order;
                  this.BondStereo = conv.BondStereo;
                  this.BondCustomProperty = conv.BondCustomProperty;
                  this.AtomCustomProperty = conv.AtomCustomProperty;
                  this.BondDictRefs = conv.BondDictRefs;
                  this.BondAromaticity = conv.BondAromaticity;
                  this.CurRef = conv.CurRef;
                  this.UnitCellParams = conv.UnitCellParams;
                  this.InChIString = conv.InChIString;
              }
              else
              {
                  Trace.TraceWarning("Cannot inherit information from module: ", convention.GetType().Name);
              }
          }
  
          public IChemFile ReturnChemFile()
          {
              return CurrentChemFile;
          }
  
          /// <summary>
          /// Clean all data about parsed data.
          /// </summary>
          protected void NewMolecule()
          {
              NewMoleculeData();
              NewAtomData();
              NewBondData();
              NewCrystalData();
              NewFormulaData();
          }
  
          /// <summary>
          /// Clean all data about the molecule itself.
          /// </summary>
          protected void NewMoleculeData()
          {
              this.InChIString = null;
          }
  
          /// <summary>
          /// Clean all data about read formulas.
          /// </summary>
          protected void NewFormulaData()
          {
              FormulaCounter = 0;
              Formula = new List<string>();
          }
  
          /// <summary>
          /// Clean all data about read atoms.
          /// </summary>
          protected void NewAtomData()
          {
              AtomCounter = 0;
              ElSym = new List<string>();
              ElId = new List<string>();
              ElTitles = new List<string>();
              FormalCharges = new List<string>();
              PartialCharges = new List<string>();
              Isotope = new List<string>();
              AtomicNumbers = new List<string>();
              ExactMasses = new List<string>();
              X3 = new List<string>();
              Y3 = new List<string>();
              Z3 = new List<string>();
              X2 = new List<string>();
              Y2 = new List<string>();
              XFract = new List<string>();
              YFract = new List<string>();
              ZFract = new List<string>();
              HCounts = new List<string>();
              AtomParities = new List<string>();
              ParityARef1 = new List<string>();
              ParityARef2 = new List<string>();
              ParityARef3 = new List<string>();
              ParityARef4 = new List<string>();
              AtomAromaticities = new List<string>();
              AtomDictRefs = new List<string>();
              SpinMultiplicities = new List<string>();
              Occupancies = new List<string>();
              AtomCustomProperty = new Dictionary<int, List<string>>();
          }
  
          /// <summary>
          /// Clean all data about read bonds.
          /// </summary>
          protected void NewBondData()
          {
              BondCounter = 0;
              BondId = new List<string>();
              BondARef1 = new List<string>();
              BondARef2 = new List<string>();
              Order = new List<string>();
              BondStereo = new List<string>();
              BondCustomProperty = new Dictionary<string, Dictionary<string, string>>();
              BondDictRefs = new List<string>();
              BondElId = new List<string>();
              BondAromaticity = new List<bool?>();
          }
  
          /// <summary>
          /// Clean all data about read bonds.
          /// </summary>
          protected void NewCrystalData()
          {
              UnitCellParams = new double[6];
              CrystalScalar = 0;
          }
  
          public virtual void StartDocument()
          {
              Trace.TraceInformation("Start XML Doc");
  
gt:             CurrentChemSequence = CurrentChemFile.Builder.NewChemSequence();