From b008a1348f9862f22722d7d42bb3edb6c61c60be Mon Sep 17 00:00:00 2001
From: Martyn Gigg <martyn.gigg@stfc.ac.uk>
Date: Mon, 1 Jul 2013 16:12:57 +0100
Subject: [PATCH] Move the remaining loaders to the new scheme. Refs #7263

---
 .../Crystal/inc/MantidCrystal/LoadIsawPeaks.h |  11 +-
 .../Framework/Crystal/src/LoadIsawPeaks.cpp   | 129 +++++------
 .../Crystal/test/LoadIsawPeaksTest.h          |  11 +-
 .../inc/MantidDataHandling/Load.h             |  36 ++-
 .../Framework/DataHandling/src/Load.cpp       | 212 +++++++++---------
 .../Kernel/inc/MantidKernel/Strings.h         |   4 +-
 Code/Mantid/Framework/Kernel/src/Strings.cpp  |   4 +-
 .../inc/MantidMDAlgorithms/LoadMD.h           |  11 +-
 .../Framework/MDAlgorithms/src/LoadMD.cpp     |  78 ++-----
 .../Framework/MDAlgorithms/test/LoadMDTest.h  |   2 +-
 10 files changed, 234 insertions(+), 264 deletions(-)

diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/LoadIsawPeaks.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/LoadIsawPeaks.h
index ac95259ebdb..54039d27d8c 100644
--- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/LoadIsawPeaks.h
+++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/LoadIsawPeaks.h
@@ -2,9 +2,8 @@
 #define MANTID_CRYSTAL_LOADISAWPEAKS_H_
     
 #include "MantidKernel/System.h"
-#include "MantidAPI/Algorithm.h" 
+#include "MantidAPI/IFileLoader.h"
 #include "MantidDataObjects/PeaksWorkspace.h"
-#include "MantidAPI/IDataFileChecker.h"
 
 namespace Mantid
 {
@@ -17,7 +16,7 @@ namespace Crystal
    * @author Janik Zikovsky, SNS
    * @date 2011-03-07 15:22:11.897153
    */
-  class DLLExport LoadIsawPeaks  : public API::IDataFileChecker
+  class DLLExport LoadIsawPeaks  : public API::IFileLoader
   {
   public:
     LoadIsawPeaks();
@@ -30,10 +29,8 @@ namespace Crystal
     /// Algorithm's category for identification
     virtual const std::string category() const { return "Crystal;DataHandling\\Isaw";}
 
-    /// do a quick check that this file can be loaded
-    bool quickFileCheck(const std::string& filePath,size_t nread,const file_header& header);
-    /// check the structure of the file and  return a value between 0 and 100 of how much this file can be loaded
-    int fileCheck(const std::string& filePath);
+    /// Returns a confidence value that this algorithm can load a file
+    virtual int confidence(Kernel::FileDescriptor & descriptor) const;
     
   private:
     /// Sets documentation strings for this algorithm
diff --git a/Code/Mantid/Framework/Crystal/src/LoadIsawPeaks.cpp b/Code/Mantid/Framework/Crystal/src/LoadIsawPeaks.cpp
index a11db7af4c1..d2683170f8f 100644
--- a/Code/Mantid/Framework/Crystal/src/LoadIsawPeaks.cpp
+++ b/Code/Mantid/Framework/Crystal/src/LoadIsawPeaks.cpp
@@ -9,6 +9,7 @@ NOTE: The instrument used is determined by reading the 'Instrument:' and 'Date:'
 
 *WIKI*/
 #include "MantidAPI/FileProperty.h"
+#include "MantidAPI/RegisterFileLoader.h"
 #include "MantidCrystal/LoadIsawPeaks.h"
 #include "MantidDataObjects/PeaksWorkspace.h"
 #include "MantidGeometry/Crystal/OrientedLattice.h"
@@ -29,7 +30,7 @@ NOTE: The instrument used is determined by reading the 'Instrument:' and 'Date:'
 #include <stdlib.h>
 #include <string>
 #include "MantidKernel/Unit.h"
-#include "MantidAPI/LoadAlgorithmFactory.h"
+
 
 using Mantid::Kernel::Strings::readToEndOfLine;
 using Mantid::Kernel::Strings::getWord;
@@ -40,9 +41,7 @@ namespace Mantid
 namespace Crystal
 {
 
-  // Register the algorithm into the AlgorithmFactory
-  DECLARE_ALGORITHM(LoadIsawPeaks)
-  DECLARE_LOADALGORITHM(LoadIsawPeaks)
+  DECLARE_FILELOADER_ALGORITHM(LoadIsawPeaks);
   
   using namespace Mantid::Kernel;
   using namespace Mantid::API;
@@ -64,6 +63,65 @@ namespace Crystal
   }
   
 
+  /**
+   * Return the confidence with with this algorithm can load the file
+   * @param descriptor A descriptor for the file
+   * @returns An integer specifying the confidence level. 0 indicates it will not be used
+   */
+  int LoadIsawPeaks::confidence(Kernel::FileDescriptor & descriptor) const
+  {
+    const std::string & extn = descriptor.extension();
+    // If the extension is peaks or integrate then give it a go
+    if(extn.compare(".peaks") != 0 && extn.compare(".integrate") != 0 ) return 0;
+
+    int confidence(0);
+    try
+    {
+      auto &in = descriptor.data();
+      // Read the header, load the instrument
+      std::string tag;
+      std::string r = getWord(in, false);
+
+      if(r.length() < 1)
+        throw std::logic_error( std::string( "No first line of Peaks file" ) );
+
+      if(r.compare("Version:") != 0)
+        throw std::logic_error(
+            std::string( "No Version: on first line of Peaks file" ) );
+
+      std::string C_version = getWord( in ,  false );
+      if( C_version.length() < 1 )
+        throw  std::logic_error( std::string( "No Version for Peaks file" ) );
+
+      getWord(in , false); //tag
+      // cppcheck-suppress unreadVariable
+      std::string C_Facility = getWord(in, false );
+
+      getWord(in , false ); //tag
+      std::string C_Instrument = getWord(in , false);
+
+      if( C_Instrument.length() < 1 )
+        throw std::logic_error(
+            std::string( "No Instrument for Peaks file" ) );
+
+      // Date: use the current date/time if not found
+      Kernel::DateAndTime C_experimentDate;
+      std::string date;
+      tag = getWord(in, false );
+      if(tag.empty())
+        date = Kernel::DateAndTime::getCurrentTime().toISO8601String();
+      else if(tag == "Date:")
+        date = getWord(in, false );
+      readToEndOfLine( in, true );
+      confidence = 95;
+    }
+    catch (std::exception & )
+    {
+    }
+    return confidence;
+  }
+
+
   //----------------------------------------------------------------------------------------------
   /// Sets documentation strings for this algorithm
   void LoadIsawPeaks::initDocs()
@@ -73,69 +131,6 @@ namespace Crystal
    }
   //----------------------------------------------------------------------------------------------
 
- /// @copydoc Mantid::API::IDataFileChecker::quickFileCheck
-  bool LoadIsawPeaks::quickFileCheck(const std::string& filePath,size_t nread,const file_header& header)
-  {
-    UNUSED_ARG(nread);
-    UNUSED_ARG(header);
-
-    std::string ext = this->extension(filePath);
-    // If the extension is peaks or integrate then give it a go
-    if( ext.compare("peaks") == 0 ) return true;
-    else if( ext.compare("integrate") == 0 ) return true;
-    else return false;
-  }
-
-  /// @copydoc Mantid::API::IDataFileChecker::fileCheck
-  int LoadIsawPeaks::fileCheck(const std::string& filePath)
-  {
-      int confidence(0);
-      try
-      {
-	    // Open the file
-	    std::ifstream in( filePath.c_str() );
-	    // Read the header, load the instrument
-	    std::string tag;
-	    std::string r = getWord( in ,  false );
-
-	    if( r.length() < 1 )
-	      throw std::logic_error( std::string( "No first line of Peaks file" ) );
-
-	    if( r.compare( std::string( "Version:" ) ) != 0 )
-	      throw std::logic_error(
-	          std::string( "No Version: on first line of Peaks file" ) );
-
-	    std::string C_version = getWord( in ,  false );
-	    if( C_version.length() < 1 )
-	      throw  std::logic_error( std::string( "No Version for Peaks file" ) );
-
-	    getWord( in ,  false ); //tag
-	    // cppcheck-suppress unreadVariable
-	    std::string C_Facility = getWord( in ,  false );
-
-	    getWord( in ,  false ); //tag
-	    std::string C_Instrument = getWord( in ,  false );
-
-	    if( C_Instrument.length() < 1 )
-	      throw std::logic_error(
-	          std::string( "No Instrument for Peaks file" ) );
-
-	    // Date: use the current date/time if not found
-	    Kernel::DateAndTime C_experimentDate;
-	    std::string date;
-	    tag = getWord( in ,  false );
-	    if(tag.empty())
-	      date = Kernel::DateAndTime::getCurrentTime().toISO8601String();
-	    else if(tag == "Date:")
-	      date = getWord( in ,  false );
-	    readToEndOfLine( in ,  true );
-	    confidence = 95;
-      }
-      catch (std::exception & )
-      {
-      }
-      return confidence;
-  }
 
   //----------------------------------------------------------------------------------------------
   /** Initialize the algorithm's properties.
diff --git a/Code/Mantid/Framework/Crystal/test/LoadIsawPeaksTest.h b/Code/Mantid/Framework/Crystal/test/LoadIsawPeaksTest.h
index 4e7763ca5ef..29270d1dbd1 100644
--- a/Code/Mantid/Framework/Crystal/test/LoadIsawPeaksTest.h
+++ b/Code/Mantid/Framework/Crystal/test/LoadIsawPeaksTest.h
@@ -22,7 +22,16 @@ class LoadIsawPeaksTest : public CxxTest::TestSuite
 {
 public:
 
-    
+  void test_Confidence()
+  {
+    LoadIsawPeaks alg;
+    alg.initialize();
+    alg.setPropertyValue("Filename", "TOPAZ_1241.integrate");
+
+    Mantid::Kernel::FileDescriptor descriptor(alg.getPropertyValue("Filename"));
+    TS_ASSERT_EQUALS(95, alg.confidence(descriptor));
+  }
+
   void test_Init()
   {
     LoadIsawPeaks alg;
diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/Load.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/Load.h
index 51ff149b64d..0cd5b24d193 100644
--- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/Load.h
+++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/Load.h
@@ -4,7 +4,7 @@
 //----------------------------------------------------------------------
 // Includes
 //----------------------------------------------------------------------
-#include "MantidAPI/IDataFileChecker.h"
+#include "MantidAPI/Algorithm.h"
 #include <Poco/Mutex.h>
 
 #include <list>
@@ -13,7 +13,7 @@ namespace Mantid
 {
   namespace DataHandling
   { 
-   
+
     /**
     Loads a workspace from a data file. The algorithm tries to determine the actual type
     of the file (raw, nxs, ...) and use the specialized loading algorith to load it.
@@ -40,8 +40,8 @@ namespace Mantid
 
     File change history is stored at: <https://github.com/mantidproject/mantid>. 
     Code Documentation is available at: <http://doxygen.mantidproject.org>
-    */ 
-    class DLLExport Load : public API::IDataFileChecker
+     */
+    class DLLExport Load : public API::Algorithm
     {
     public:
       /// Default constructor
@@ -60,16 +60,12 @@ namespace Mantid
     private:
       /// Sets documentation strings for this algorithm
       virtual void initDocs();
-      /// Quick file always returns false here
-      virtual bool quickFileCheck(const std::string& filePath,size_t nread,const file_header& header);
-      /// file check by looking at the structure of the data file
-      virtual int fileCheck(const std::string& filePath);
       /// This method returns shared pointer to a load algorithm which got 
       /// the highest preference after file check. 
-      API::IDataFileChecker_sptr getFileLoader(const std::string& filePath);
+      API::IAlgorithm_sptr getFileLoader(const std::string& filePath);
       /// Declare any additional input properties from the concrete loader
-      void declareLoaderProperties(const API::IDataFileChecker_sptr loader);
-      
+      void declareLoaderProperties(const API::IAlgorithm_sptr & loader);
+
       /// Initialize the static base properties
       void init();
       /// Execute
@@ -83,16 +79,16 @@ namespace Mantid
       /// Overrides the cancel() method to call m_loader->cancel()
       void cancel();
       /// Create the concrete instance use for the actual loading.
-      API::IDataFileChecker_sptr createLoader(const std::string & name, const double startProgress = -1.0, 
-					      const double endProgress=-1.0, const bool logging = true) const;
+      API::IAlgorithm_sptr createLoader(const std::string & name, const double startProgress = -1.0,
+          const double endProgress=-1.0, const bool logging = true) const;
       /// Set the loader option for use as a Child Algorithm.
-      void setUpLoader(API::IDataFileChecker_sptr loader, const double startProgress = -1.0, 
-		       const double endProgress=-1.0,  const bool logging = true) const;
+      void setUpLoader(API::IAlgorithm_sptr & loader, const double startProgress = -1.0,
+          const double endProgress=-1.0,  const bool logging = true) const;
       /// Set the output workspace(s)
-      void setOutputWorkspace(const API::IDataFileChecker_sptr & loader);
+      void setOutputWorkspace(const API::IAlgorithm_sptr & loader);
       /// Retrieve a pointer to the output workspace from the Child Algorithm
       API::Workspace_sptr getOutputWorkspace(const std::string & propName, 
-					     const API::IDataFileChecker_sptr & loader) const;
+          const API::IAlgorithm_sptr & loader) const;
 
       /// Load a file to a given workspace name.
       API::Workspace_sptr loadFileToWs(const std::string & fileName, const std::string & wsName);
@@ -105,10 +101,12 @@ namespace Mantid
       /// The base properties
       std::set<std::string> m_baseProps;
       /// The actual loader
-      API::IDataFileChecker_sptr m_loader;
+      API::IAlgorithm_sptr m_loader;
+      /// The name of the property that will be passed the property from our Filename
+      std::string m_filenamePropName;
       /// Mutex for temporary fix for #5963
       static Poco::Mutex m_mutex;
-     };
+    };
 
   } // namespace DataHandling
 } // namespace Mantid
diff --git a/Code/Mantid/Framework/DataHandling/src/Load.cpp b/Code/Mantid/Framework/DataHandling/src/Load.cpp
index 78077edd060..3c23011d23d 100644
--- a/Code/Mantid/Framework/DataHandling/src/Load.cpp
+++ b/Code/Mantid/Framework/DataHandling/src/Load.cpp
@@ -32,12 +32,15 @@ Loading multiple files is also possible with <code>Load</code>, as well as works
 // Includes
 //----------------------------------------------------------------------
 #include "MantidDataHandling/Load.h"
-#include "MantidAPI/MultipleFileProperty.h"
+#include "MantidAPI/AlgorithmManager.h"
+#include "MantidAPI/FileProperty.h"
+#include "MantidAPI/FrameworkManager.h"
 #include "MantidAPI/IEventWorkspace.h"
+#include "MantidAPI/IMDEventWorkspace.h"
 #include "MantidAPI/IWorkspaceProperty.h"
-#include "MantidKernel/ArrayProperty.h"
 #include "MantidAPI/LoadAlgorithmFactory.h"
-#include "MantidAPI/AlgorithmManager.h"
+#include "MantidAPI/MultipleFileProperty.h"
+#include "MantidKernel/ArrayProperty.h"
 #include "MantidKernel/FacilityInfo.h"
 
 #include <Poco/Path.h>
@@ -47,7 +50,6 @@ Loading multiple files is also possible with <code>Load</code>, as well as works
 #include <functional>
 #include <numeric>
 #include <set>
-#include "MantidAPI/IMDEventWorkspace.h"
 #include <cstdio>
 
 namespace
@@ -164,7 +166,7 @@ namespace Mantid
     //--------------------------------------------------------------------------
 
     /// Default constructor
-    Load::Load() : IDataFileChecker(), m_baseProps()
+    Load::Load() : Algorithm(), m_baseProps(), m_loader(), m_filenamePropName()
     {
     }
 
@@ -177,7 +179,7 @@ namespace Mantid
     {
       // Call base class method in all cases.
       // For a filename property is deals with resolving the full path.
-      IDataFileChecker::setPropertyValue(name, value);
+      Algorithm::setPropertyValue(name, value);
 
       std::string NAME(name);
       std::transform(name.begin(),name.end(),NAME.begin(),toupper);
@@ -186,21 +188,20 @@ namespace Mantid
         // Get back full path before passing to getFileLoader method, and also
         // find out whether this is a multi file load.
         std::vector<std::string> fileNames = flattenVecOfVec(getProperty("Filename"));
-        // If it's a single file load, then it's fine to change loader.
+        //If it's a single file load, then it's fine to change loader.
         if(fileNames.size() == 1)
         {
-          IDataFileChecker_sptr loader = getFileLoader(getPropertyValue(name));
+          IAlgorithm_sptr loader = getFileLoader(getPropertyValue(name));
           assert(loader); // (getFileLoader should throw if no loader is found.)
           declareLoaderProperties(loader);
         }
-
         // Else we've got multiple files, and must enforce the rule that only one type of loader is allowed.
         // Allowing more than one would mean that "extra" properties defined by the class user (for example
         // "LoadLogFiles") are potentially ambiguous.
         else if(fileNames.size() > 1)
         {
-          IDataFileChecker_sptr loader = getFileLoader(fileNames[0]);
-          
+          IAlgorithm_sptr loader = getFileLoader(fileNames[0]);
+
           // If the first file has a loader ...
           if( loader )
           {
@@ -226,109 +227,118 @@ namespace Mantid
     // Private methods
     //--------------------------------------------------------------------------
 
-    /**
-    * Quick file always returns false here
-    * @param filePath :: File path
-    * @param nread :: Number of bytes read
-    * @param header :: A buffer containing the nread bytes
-    */
-    bool Load::quickFileCheck(const std::string& filePath,size_t nread,const file_header& header)
-    {
-      (void)filePath; (void)nread; (void)header;
-      return false;
-    }
-
-    /**
-    * File check by looking at the structure of the data file
-    * @param filePath :: The full file path
-    * @returns -1
-    */
-    int Load::fileCheck(const std::string& filePath)
-    {
-      (void)filePath;
-      return -1;
-    }
-
     /** 
     * Get a shared pointer to the load algorithm with highest preference for loading
     * @param filePath :: path of the file
     * @returns A shared pointer to the unmanaged algorithm
     */
-    API::IDataFileChecker_sptr Load::getFileLoader(const std::string& filePath)
+    API::IAlgorithm_sptr Load::getFileLoader(const std::string& filePath)
     {
-      /* Open the file and read in the first bufferSize bytes - these will
-      * be used to determine the type of the file
-      */
-      FILE* fp = fopen(filePath.c_str(), "rb");
-      if (fp == NULL)
+//      /* Open the file and read in the first bufferSize bytes - these will
+//      * be used to determine the type of the file
+//      */
+//      FILE* fp = fopen(filePath.c_str(), "rb");
+//      if (fp == NULL)
+//      {
+//        throw Kernel::Exception::FileError("Unable to open the file:", filePath);
+//      }
+//      file_header header;
+//      size_t nread = fread(&header,sizeof(unsigned char), g_hdr_bytes, fp);
+//      // Ensure the character string is null terminated.
+//      header.full_hdr[g_hdr_bytes] = '\0';
+//
+//      if (fclose(fp) != 0)
+//      {
+//        throw std::runtime_error("Error while closing file \"" + filePath + "\"");
+//      }
+//
+//      Poco::Mutex::ScopedLock lock( m_mutex );
+//
+//      // Iterate through all loaders and attempt to find the best qualified for the job.
+//      // Each algorithm has a quick and long file check. The long version returns an integer
+//      // giving its certainty about be able to load the file. The highest wins.
+//      std::vector<std::string> loaderNames = API::LoadAlgorithmFactory::Instance().getKeys();
+//      int highestPref(0);
+//      API::IDataFileChecker_sptr winningLoader;
+//      std::vector<std::string>::const_iterator cend = loaderNames.end();
+//      for( std::vector<std::string>::const_iterator citr = loaderNames.begin(); citr != cend;
+//        ++citr )
+//      {
+//        IDataFileChecker_sptr loader = API::LoadAlgorithmFactory::Instance().create(*citr);
+//        try
+//        {
+//          if( loader->quickFileCheck(filePath, nread, header) )
+//          {
+//            int pref = loader->fileCheck(filePath);
+//            // Can't just pick the first as there might be one later in the list with a higher
+//            // preference
+//            if( pref > highestPref )
+//            {
+//              highestPref = pref;
+//              winningLoader = loader;
+//            }
+//          }
+//        }
+//        catch (std::exception & e)
+//        {
+//          g_log.debug() << "Error running file check of " <<  loader->name() << std::endl;
+//          g_log.debug() << e.what() << std::endl;
+//
+//        }
+//
+//      }
+//
+//      if( !winningLoader )
+//      {
+//        // Clear what may have been here previously
+//        setPropertyValue("LoaderName", "");
+//        throw std::runtime_error("Cannot find an algorithm that is able to load \"" + filePath + "\".\n"
+//                                 "Check that the file is a supported type.");
+//      }
+//      g_log.debug() << "Winning loader is " <<  winningLoader->name() << std::endl;
+//      setPropertyValue("LoaderName", winningLoader->name());
+//      winningLoader->initialize();
+//      setUpLoader(winningLoader);
+//      return winningLoader;
+      std::string winningLoader;
+      try
       {
-        throw Kernel::Exception::FileError("Unable to open the file:", filePath);
+        CALLGRIND_START_INSTRUMENTATION;
+        winningLoader = API::FileLoaderRegistry::Instance().chooseLoader(filePath);
+        CALLGRIND_STOP_INSTRUMENTATION;
       }
-      file_header header;
-      size_t nread = fread(&header,sizeof(unsigned char), g_hdr_bytes, fp);
-      // Ensure the character string is null terminated.
-      header.full_hdr[g_hdr_bytes] = '\0';
-
-      if (fclose(fp) != 0)
+      catch(Exception::NotFoundError&)
       {
-        throw std::runtime_error("Error while closing file \"" + filePath + "\"");
-      } 
-
-      Poco::Mutex::ScopedLock lock( m_mutex );
-
-      // Iterate through all loaders and attempt to find the best qualified for the job.
-      // Each algorithm has a quick and long file check. The long version returns an integer
-      // giving its certainty about be able to load the file. The highest wins.
-      std::vector<std::string> loaderNames = API::LoadAlgorithmFactory::Instance().getKeys();
-      int highestPref(0);
-      API::IDataFileChecker_sptr winningLoader;
-      std::vector<std::string>::const_iterator cend = loaderNames.end();
-      for( std::vector<std::string>::const_iterator citr = loaderNames.begin(); citr != cend;
-        ++citr )
+        // Clear what may have been here previously
+        setPropertyValue("LoaderName", "");
+        throw std::runtime_error("Cannot find an algorithm that is able to load \"" + filePath + "\".\n"
+            "Check that the file is a supported type.");
+      }
+      const IAlgorithm_sptr loader = AlgorithmManager::Instance().create(winningLoader,-1);
+      loader->initialize();
+      // Use the first file property as the main Filename
+      const auto & props = loader->getProperties();
+      for(auto it = props.begin(); it != props.end(); ++it)
       {
-        IDataFileChecker_sptr loader = API::LoadAlgorithmFactory::Instance().create(*citr);
-        try
+        if(auto *fp = dynamic_cast<API::FileProperty*>(*it))
         {
-          if( loader->quickFileCheck(filePath, nread, header) )
-          {
-            int pref = loader->fileCheck(filePath);
-            // Can't just pick the first as there might be one later in the list with a higher
-            // preference
-            if( pref > highestPref )
-            {
-              highestPref = pref;
-              winningLoader = loader;
-            }
-          }
-        }
-        catch (std::exception & e)
-        {
-          g_log.debug() << "Error running file check of " <<  loader->name() << std::endl;
-          g_log.debug() << e.what() << std::endl;
-
+          m_filenamePropName = fp->name();
+          break;
         }
-
       }
-
-      if( !winningLoader )
+      if(m_filenamePropName.empty())
       {
-        // Clear what may have been here previously
         setPropertyValue("LoaderName", "");
-        throw std::runtime_error("Cannot find an algorithm that is able to load \"" + filePath + "\".\n"
-                                 "Check that the file is a supported type.");
+        throw std::runtime_error("Cannot find FileProperty on " + winningLoader + " algorithm.");
       }
-      g_log.debug() << "Winning loader is " <<  winningLoader->name() << std::endl;
-      setPropertyValue("LoaderName", winningLoader->name());
-      winningLoader->initialize();
-      setUpLoader(winningLoader);
-      return winningLoader;
+      return loader;
     }
 
     /**
     * Declare any additional properties of the concrete loader here
     * @param loader A pointer to the concrete loader
     */
-    void Load::declareLoaderProperties(const IDataFileChecker_sptr loader)
+    void Load::declareLoaderProperties(const API::IAlgorithm_sptr & loader)
     {
       // If we have switch loaders then the concrete loader will have different properties
       // so take care of ensuring Load has the correct ones
@@ -345,12 +355,11 @@ namespace Mantid
       }
 
       const std::vector<Property*> &loaderProps = loader->getProperties();
-      const std::string filePropName(loader->filePropertyName());
       size_t numProps(loaderProps.size());
       for (size_t i = 0; i < numProps; ++i)
       {
         Property* loadProp = loaderProps[i];
-        if( loadProp->name() == filePropName ) continue;
+        if( loadProp->name() == m_filenamePropName ) continue;
         try
         {
           Property * propClone = loadProp->clone();
@@ -447,7 +456,7 @@ namespace Mantid
         {
           m_loader->setPropertyValue(propName, getPropertyValue(propName));
         }
-        else if( propName == m_loader->filePropertyName() )
+        else if( propName == m_filenamePropName )
         {
           m_loader->setPropertyValue(propName, getPropertyValue("Filename"));
         }
@@ -554,11 +563,10 @@ namespace Mantid
     * algorithm where this child algorithm ends
     * @param logging :: Set to false to disable logging from the child algorithm
     */
-    API::IDataFileChecker_sptr Load::createLoader(const std::string & name, const double startProgress, 
+    API::IAlgorithm_sptr Load::createLoader(const std::string & name, const double startProgress,
       const double endProgress, const bool logging) const
     {
-      IDataFileChecker_sptr loader = boost::static_pointer_cast<IDataFileChecker>(
-        API::AlgorithmManager::Instance().createUnmanaged(name));
+      API::IAlgorithm_sptr loader = API::AlgorithmManager::Instance().createUnmanaged(name);
       loader->initialize();
       if( !loader )
       {
@@ -575,8 +583,8 @@ namespace Mantid
      * @param endProgress :: The end progress fraction
      * @param logging:: If true, enable logging
      */
-    void Load::setUpLoader(API::IDataFileChecker_sptr loader, const double startProgress, 
-			   const double endProgress, const bool logging) const
+    void Load::setUpLoader(API::IAlgorithm_sptr & loader, const double startProgress,
+        const double endProgress, const bool logging) const
     {
       //Set as a child so that we are in control of output storage
       loader->setChild(true);
@@ -604,7 +612,7 @@ namespace Mantid
     * Set the output workspace(s) if the load's return workspace has type API::Workspace
     * @param loader :: Shared pointer to load algorithm
     */
-    void Load::setOutputWorkspace(const API::IDataFileChecker_sptr & loader)
+    void Load::setOutputWorkspace(const API::IAlgorithm_sptr & loader)
     {
       // Go through each OutputWorkspace property and check whether we need to make a counterpart here
       const std::vector<Property*> & loaderProps = loader->getProperties();
@@ -634,7 +642,7 @@ namespace Mantid
     * @returns A pointer to the OutputWorkspace property of the Child Algorithm
     */
     API::Workspace_sptr Load::getOutputWorkspace(const std::string & propName,
-      const API::IDataFileChecker_sptr & loader) const
+      const API::IAlgorithm_sptr & loader) const
     {
       // @todo Need to try and find a better way using the getValue methods
       try
diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h
index 834fa70f570..6ea32d2dfe0 100644
--- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h
+++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Strings.h
@@ -152,9 +152,9 @@ namespace Mantid
       float getVAXnum(const float A);
 
       /// Eat everything from the stream until the next EOL
-      MANTID_KERNEL_DLL void readToEndOfLine( std::ifstream& in ,  bool ConsumeEOL );
+      MANTID_KERNEL_DLL void readToEndOfLine( std::istream& in ,  bool ConsumeEOL );
       /// Returns the next word in the stream
-      MANTID_KERNEL_DLL std::string getWord( std::ifstream &in ,  bool consumeEOL );
+      MANTID_KERNEL_DLL std::string getWord( std::istream &in ,  bool consumeEOL );
       ///  function parses a path, found in input string "path" and returns vector of the folders contributed into the path */
       MANTID_KERNEL_DLL size_t split_path(const std::string &path, std::vector<std::string> &path_components);
 
diff --git a/Code/Mantid/Framework/Kernel/src/Strings.cpp b/Code/Mantid/Framework/Kernel/src/Strings.cpp
index 33a8de152f4..c2c1ba8b2b9 100644
--- a/Code/Mantid/Framework/Kernel/src/Strings.cpp
+++ b/Code/Mantid/Framework/Kernel/src/Strings.cpp
@@ -913,7 +913,7 @@ namespace Mantid
        * @param consumeEOL :: set to true to remove the new lines at the end of the line
        * @return a string with the word read in
        */
-      std::string getWord( std::ifstream &in ,  bool consumeEOL )
+      std::string getWord( std::istream &in ,  bool consumeEOL )
       {
         std::string s;
         char c = 0;
@@ -949,7 +949,7 @@ namespace Mantid
        * @param in :: stream input
        * @param ConsumeEOL :: set to true to remove the new lines at the end of the line
        */
-      void readToEndOfLine( std::ifstream& in ,  bool ConsumeEOL )
+      void readToEndOfLine( std::istream& in ,  bool ConsumeEOL )
       {
         while( in.good() && getWord( in ,  false ).length() > 0  )
           getWord( in ,  false );
diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/LoadMD.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/LoadMD.h
index e2cb4b745a6..9691fd76181 100644
--- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/LoadMD.h
+++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/LoadMD.h
@@ -1,11 +1,10 @@
 #ifndef MANTID_MDEVENTS_LOADMD_H_
 #define MANTID_MDEVENTS_LOADMD_H_
 
-#include "MantidAPI/Algorithm.h"
+#include "MantidAPI/IHDFFileLoader.h"
 #include "MantidAPI/IMDEventWorkspace.h"
 #include "MantidKernel/System.h"
 #include "MantidMDEvents/MDEventWorkspace.h"
-#include "MantidAPI/IDataFileChecker.h"
 
 namespace Mantid
 {
@@ -37,7 +36,7 @@ namespace MDAlgorithms
     File change history is stored at: <https://github.com/mantidproject/mantid>
     Code Documentation is available at: <http://doxygen.mantidproject.org>
   */
-  class DLLExport LoadMD : public API::IDataFileChecker
+  class DLLExport LoadMD : public API::IHDFFileLoader
   {
   public:
     LoadMD();
@@ -50,10 +49,8 @@ namespace MDAlgorithms
     /// Algorithm's category for identification
     virtual const std::string category() const { return "MDAlgorithms";}
 
-    /// do a quick check that this file can be loaded
-    bool quickFileCheck(const std::string& filePath,size_t nread,const file_header& header);
-    /// check the structure of the file and  return a value between 0 and 100 of how much this file can be loaded
-    int fileCheck(const std::string& filePath);
+    /// Returns a confidence value that this algorithm can load a file
+    int confidence(const Kernel::HDFDescriptor & descriptor) const;
 
   private:
     /// Sets documentation strings for this algorithm
diff --git a/Code/Mantid/Framework/MDAlgorithms/src/LoadMD.cpp b/Code/Mantid/Framework/MDAlgorithms/src/LoadMD.cpp
index 5d1fd2a973e..9bd468d27f8 100644
--- a/Code/Mantid/Framework/MDAlgorithms/src/LoadMD.cpp
+++ b/Code/Mantid/Framework/MDAlgorithms/src/LoadMD.cpp
@@ -21,7 +21,7 @@ and used by other algorithms, they should not be needed in daily use.
 #include "MantidAPI/ExperimentInfo.h"
 #include "MantidAPI/FileProperty.h"
 #include "MantidAPI/IMDEventWorkspace.h"
-#include "MantidAPI/LoadAlgorithmFactory.h"
+#include "MantidAPI/RegisterFileLoader.h"
 #include "MantidGeometry/MDGeometry/IMDDimension.h"
 #include "MantidGeometry/MDGeometry/IMDDimensionFactory.h"
 #include "MantidGeometry/MDGeometry/MDDimensionExtents.h"
@@ -56,10 +56,7 @@ namespace Mantid
   namespace MDAlgorithms
   {
 
-    // Register the algorithm into the AlgorithmFactory
-    DECLARE_ALGORITHM(LoadMD);
-    DECLARE_LOADALGORITHM(LoadMD);
-
+    DECLARE_HDF_FILELOADER_ALGORITHM(LoadMD);
 
     //----------------------------------------------------------------------------------------------
     /** Constructor
@@ -76,6 +73,26 @@ namespace Mantid
     }
 
 
+    /**
+     * Return the confidence with with this algorithm can load the file
+     * @param descriptor A descriptor for the file
+     * @returns An integer specifying the confidence level. 0 indicates it will not be used
+     */
+    int LoadMD::confidence(const Kernel::HDFDescriptor & descriptor) const
+    {
+      int confidence(0);
+      const auto & rootPathNameType = descriptor.firstEntryNameType();
+      if(rootPathNameType.second != "NXentry") return 0;
+      if(descriptor.pathExists("/" + rootPathNameType.first + "MDEventWorkspace") ||
+         descriptor.pathExists("/" + rootPathNameType.first + "MDHistoWorkspace"))
+      {
+        return 95;
+      }
+      else return 0;
+      return confidence;
+    }
+
+
     //----------------------------------------------------------------------------------------------
     /// Sets documentation strings for this algorithm
     void LoadMD::initDocs()
@@ -113,57 +130,6 @@ namespace Mantid
       declareProperty(new WorkspaceProperty<IMDWorkspace>("OutputWorkspace","",Direction::Output), "Name of the output MDEventWorkspace.");
     }
 
-
-
-    //-------------------------------------------------------------------------------------------------
-    /** Do a quick file type check by looking at the first 100 bytes of the file
-    *  @param filePath :: path of the file including name.
-    *  @param nread :: no.of bytes read
-    *  @param header :: The first 100 bytes of the file as a union
-    *  @return true if the given file is of type which can be loaded by this algorithm
-    */
-    bool LoadMD::quickFileCheck(const std::string& filePath,size_t nread, const file_header& header)
-    {
-      std::string ext = this->extension(filePath);
-      // If the extension is nxs then give it a go
-      if( ext.compare("nxs") == 0 ) return true;
-
-      // If not then let's see if it is a HDF file by checking for the magic cookie
-      if ( nread >= sizeof(int32_t) && (ntohl(header.four_bytes) == g_hdf_cookie) ) return true;
-      return false;
-    }
-
-    //-------------------------------------------------------------------------------------------------
-    /** Checks the file by opening it and reading few lines
-    *  @param filePath :: name of the file inluding its path
-    *  @return an integer value how much this algorithm can load the file
-    */
-    int LoadMD::fileCheck(const std::string& filePath)
-    {
-      int confidence(0);
-      typedef std::map<std::string,std::string> string_map_t;
-      try
-      {
-        ::NeXus::File file = ::NeXus::File(filePath);
-        string_map_t entries = file.getEntries();
-        for(string_map_t::const_iterator it = entries.begin(); it != entries.end(); ++it)
-        {
-          if ( (it->second == "NXentry") &&
-            ((it->first == "MDEventWorkspace") || (it->first == "MDHistoWorkspace")) )
-            confidence = 95;
-        }
-        file.close();
-      }
-      catch(::NeXus::Exception&)
-      {
-      }
-      return confidence;
-    }
-
-
-
-
-
     //----------------------------------------------------------------------------------------------
     /** Load the ExperimentInfo blocks, if any, in the NXS file
     *
diff --git a/Code/Mantid/Framework/MDAlgorithms/test/LoadMDTest.h b/Code/Mantid/Framework/MDAlgorithms/test/LoadMDTest.h
index d7da4227669..f325c38874f 100644
--- a/Code/Mantid/Framework/MDAlgorithms/test/LoadMDTest.h
+++ b/Code/Mantid/Framework/MDAlgorithms/test/LoadMDTest.h
@@ -26,7 +26,7 @@ using namespace Mantid::Kernel;
 class LoadMDTest : public CxxTest::TestSuite
 {
 public:
-    
+
   void test_Init()
   {
     LoadMD alg;
-- 
GitLab