       1 package MoleculeFileIO;
       2 #
       3 # File: MoleculeFileIO.pm
       4 # Author: Manish Sud <msud@san.rr.com>
       5 #
       6 # Copyright (C) 2018 Manish Sud. All rights reserved.
       7 #
       8 # This file is part of MayaChemTools.
       9 #
      10 # MayaChemTools is free software; you can redistribute it and/or modify it under
      11 # the terms of the GNU Lesser General Public License as published by the Free
      12 # Software Foundation; either version 3 of the License, or (at your option) any
      13 # later version.
      14 #
      15 # MayaChemTools is distributed in the hope that it will be useful, but without
      16 # any warranty; without even the implied warranty of merchantability of fitness
      17 # for a particular purpose.  See the GNU Lesser General Public License for more
      18 # details.
      19 #
      20 # You should have received a copy of the GNU Lesser General Public License
      21 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or
      22 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330,
      23 # Boston, MA, 02111-1307, USA.
      24 #
      25
      26 use strict;
      27 use Carp;
      28 use Exporter;
      29 use Scalar::Util ();
      30 use FileIO::SDFileIO;
      31 use FileIO::MDLMolFileIO;
      32
      33 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
      34
      35 @ISA = qw(Exporter);
      36 @EXPORT = qw();
      37 @EXPORT_OK = qw(IsSupportedMoleculeFileFormat);
      38
      39 %EXPORT_TAGS = (all  => [@EXPORT, @EXPORT_OK]);
      40
      41 # Setup class variables...
      42 my($ClassName);
      43 _InitializeClass();
      44
      45 # Class constructor...
      46 sub new {
      47   my($Class, %NamesAndValues) = @_;
      48
      49   # Initialize object...
      50   my $This = {};
      51   bless $This, ref($Class) || $Class;
      52   $This->_InitializeMoleculeFileIO();
      53
      54   $This->_InitializeMoleculeFileIOProperties(%NamesAndValues);
      55
      56   return $This;
      57 }
      58
      59 # Initialize object data...
      60 #
      61 sub _InitializeMoleculeFileIO {
      62   my($This) = @_;
      63
      64   # Reference to specific FileIO object...
      65   $This->{FileIORef} = '';
      66
      67   return $This;
      68 }
      69
      70 # Initialize class ...
      71 sub _InitializeClass {
      72   #Class name...
      73   $ClassName = __PACKAGE__;
      74
      75 }
      76
      77 # Initialize object properties......
      78 #
      79 sub _InitializeMoleculeFileIOProperties {
      80   my($This, %NamesAndValues) = @_;
      81
      82   if (!exists $NamesAndValues{Name}) {
      83     croak "Error: ${ClassName}->New: Object can't be instantiated without specifying file name...";
      84   }
      85
      86   if (!exists $NamesAndValues{Mode}) {
      87     $NamesAndValues{Mode} = 'Read';
      88   }
      89
      90   # Make sure its a supported format and intialize FileIO object reference...
      91   $This->_SetFileIORef(%NamesAndValues);
      92
      93   return $This;
      94 }
      95
      96 # Setup FileIO object reference...
      97 sub _SetFileIORef {
      98   my($This, %NamesAndValues) = @_;
      99   my($Name, $Status, $Format, $IOPackageName);
     100
     101   $Name = $NamesAndValues{Name};
     102
     103   ($Status, $Format, $IOPackageName) = $This->IsSupportedMoleculeFileFormat($Name);
     104   if (!$Status) {
     105     croak "Error: ${ClassName}->New: Object can't be instantiated: File format, $Name, is not supported: Currently supported file formats are: SDF, MDLMol...";
     106   }
     107
     108   $This->{FileIORef} = ${IOPackageName}->new(%NamesAndValues);
     109
     110   return $This;
     111 }
     112
     113 # Is it a supported file format?
     114 #
     115 # In scalar context only status is returned; otherwise, file format and file IO package name is also
     116 # returned.
     117 #
     118 # Note:
     119 #   . To support additional file formats, this is the only method which needs to be changed.
     120 #
     121 #   . Currently supported file formats are:
     122 #
     123 #      SDF         .sdf, .sd
     124 #      MDLMol   .mol
     125 #
     126 sub IsSupportedMoleculeFileFormat {
     127   my($FirstParameter, $SecondParameter) = @_;
     128   my($This, $Name);
     129
     130   if ((@_ == 2) && (_IsMoleculeFileIO($FirstParameter))) {
     131     ($This, $Name) = ($FirstParameter, $SecondParameter);
     132   }
     133   else {
     134     ($Name) = ($FirstParameter);
     135   }
     136   my($Status, $Format, $IOPackageName);
     137
     138   $Status = 0; $Format = 'NotSupported'; $IOPackageName = 'Unknown';
     139
     140   FORMAT: {
     141     if (FileIO::SDFileIO::IsSDFile($Name)) { $Status = 1; $Format = 'SDF'; $IOPackageName = 'FileIO::SDFileIO'; last FORMAT; }
     142     if (FileIO::MDLMolFileIO::IsMDLMolFile($Name)) { $Status = 1; $Format = 'MDLMol'; $IOPackageName = 'FileIO::MDLMolFileIO'; last FORMAT; }
     143     $Status = 0; $Format = 'NotSupported'; $IOPackageName = 'Unknown';
     144   }
     145
     146   return wantarray ? ($Status, $Format, $IOPackageName) : $Status;
     147 }
     148
     149 # Prohibit file ref change...
     150 #
     151 sub SetFileIORef {
     152   my($This, $Value) = @_;
     153
     154   carp "Warning: ${ClassName}->SetFileIORef: Explicit setting of file ref is not supported...";
     155
     156   return $This;
     157 }
     158
     159 # Prohibit file name change...
     160 #
     161 sub SetName {
     162   my($This, $Name) = @_;
     163
     164   carp "Warning: ${ClassName}->SetName: Explicit setting of file name is not supported: It must be set during object instantiation...";
     165
     166   return $This;
     167 }
     168
     169 # Prohibit file mode change...
     170 #
     171 sub SetMode {
     172   my($This, $Mode) = @_;
     173
     174   carp "Warning: ${ClassName}->SetMode: Explicit setting of file mode is not supported: It must be set during object instantiation...";
     175
     176   return $This;
     177 }
     178
     179 # Open file in a specific mode; default mode is Read only.
     180 # Supported mode values are: Read, Write, Append, <, >, >>, r, w, a
     181 #
     182 sub Open {
     183   my($This, $Mode) = @_;
     184
     185   return $This->{FileIORef}->Open($Mode);
     186 }
     187
     188 # close file...
     189 sub Close {
     190   my($This) = @_;
     191
     192   return $This->{FileIORef}->Close();
     193 }
     194
     195 # Read molecule string from file and return a molecule object...
     196 sub ReadMolecule {
     197   my($This) = @_;
     198
     199   return $This->{FileIORef}->ReadMolecule();
     200 }
     201
     202 # Retrieve molecule string from file...
     203 sub ReadMoleculeString {
     204   my($This) = @_;
     205
     206   return $This->{FileIORef}->ReadMoleculeString();
     207 }
     208
     209 # Write molecule using molecule object...
     210 sub WriteMolecule {
     211   my($This, $Molecule) = @_;
     212
     213   return $This->{FileIORef}->WriteMolecule($Molecule);
     214 }
     215
     216 # Is it a MoleculeFileIO object?
     217 sub _IsMoleculeFileIO {
     218   my($Object) = @_;
     219
     220   return (Scalar::Util::blessed($Object) && $Object->isa($ClassName)) ? 1 : 0;
     221 }
     222