text: /*=========================================================================
   *
   *  Copyright NumFOCUS
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *         https://www.apache.org/licenses/LICENSE-2.0.txt
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   *=========================================================================*/
  
  #ifndef itkDOMReader_h
  #define itkDOMReader_h
  
  #include "itkDOMNodeXMLReader.h"
  #include "itkObject.h"
  #include "itkLogger.h"
  
  namespace itk
  {
  
  /**
   * \class DOMReader
   * \brief Class to read an ITK object from an XML file or a DOM object, using the DOM APIs.
   *
   * End-users need to derive from this class to implement readers for user objects. In subclasses, users need
   * to provide an implementation for the virtual functions GenerateData(-,-).
   *
   * This class performs similar functions as the XMLReader - both provide the base for handling object reading from
   * an XML source. The difference is that, readers derived from this class perform object reading using the
   * easy-to-use DOM APIs, while XMLReader-based readers use the more error-prone SAX (Simple API for XML) APIs.
   *
   * Internally, this class first implicitly creates an intermediate DOM object from the input XML file using the
   * DOMNodeXMLReader, then performs output object generation by pulling information from the DOM object.
   *
   * Note: Though this class behaves similar to ProcessObject, it is not derived from ProcessObject. This is
   *       because many user objects to be read, e.g., registrations, transforms, optimizers, and so on, are not objects
   *       of type DataObject, thus this class cannot be connected to an ITK process pipeline.
   *
   * The following code snippet demonstrates how to use a DOM-based reader that is derived from this class:
   *
     \code
         itk::MyObjectType::Pointer output_object;
         const char* input_xml_file_name = ...
         itk::MyObjectDOMReader::Pointer reader = itk::MyObjectDOMReader::New();
         reader->SetFileName( input_xml_file_name );
         reader->Update();
         output_object = reader->GetOutput();
     \endcode
   *
   * \sa XMLReader
   * \sa DOMNodeXMLReader
   * \sa DOMNode
   *
   * \ingroup ITKIOXML
   */
  template <typename TOutput>
  class ITK_TEMPLATE_EXPORT DOMReader : public Object
  {
  public:
    ITK_DISALLOW_COPY_AND_MOVE(DOMReader);
  
    /** Standard class type aliases. */
    using Self = DOMReader;
  
    itkTypeMacro(DOMReader, Object);
  
    using OutputType = TOutput;
  
    using DOMNodeType = DOMNode;
    using DOMNodePointer = typename DOMNodeType::Pointer;
  
    using LoggerType = Logger;
    using LoggerPointer = typename LoggerType::Pointer;
  
    /** Set the input XML filename. */
    itkSetStringMacro(FileName);
  
    /** Get the input XML filename. */
    itkGetStringMacro(FileName);
  
    /**
     * The output object will be created automatically, but the user
     * can appoint a user object as the output by calling this function.
     */
    virtual void
    SetOutput(OutputType * output);
  
    /** Get the output object for full access. */
    OutputType *
    GetOutput();
  
    /** Get the output object for read-only access. */
    const OutputType *
    GetOutput() const;
  
    /**
     * Return the internal logger so that users can change the
     * output format or add/remove logging destinations.
     */
    itkGetConstMacro(Logger, LoggerType *);
  
    /**
     * Function called by Update() or end-users to generate the output object from a DOM object.
     * Some derived readers may accept an incomplete DOM object during the reading process, in those cases
     * the optional argument 'userdata' can be used to provide the missed information.
     */
    void
    Update(const DOMNodeType * inputdom, const void * userdata = nullptr);
  
    /**
     * Function called by end-users to generate the output object from the input XML file.
     */
    virtual void
    Update();
  
  protected:
    DOMReader();
  
    /**
     * Function to be implemented in subclasses. It is called automatically
     * when update functions are performed. It should fill the contents of the output object by pulling
     * information from the intermediate DOM object.
     * Some derived readers may accept an incomplete DOM object during the reading process, in those cases
     * the optional argument 'userdata' can be used to provide the missed information.
     */
    virtual void
    GenerateData(const DOMNodeType * inputdom, const void * userdata) = 0;
  
  private:
    /** Get/Set the intermediate DOM object. */
    itkSetObjectMacro(IntermediateDOM, DOMNodeType);
    itkGetModifiableObjectMacro(IntermediateDOM, DOMNodeType);
  
    /** Variable to hold the input XML file name. */
    std::string m_FileName;
  
    /** Variable to hold the output object, created internally or supplied by the user. */
    OutputType * m_Output;
    /** Variable to hold the output object if it is a smart object. */
    typename LightObject::Pointer m_OutputHolder;
  
    /** Variable to hold the intermediate DOM object. */
    DOMNodePointer m_IntermediateDOM;
  
    /** Variable to log various messages during the reading process. */
    mutable LoggerPointer m_Logger;
  };
  
  } // namespace itk
  
  #ifndef ITK_MANUAL_INSTANTIATION
  #  include "itkDOMReader.hxx"
  #endif
  
  #endif // itkDOMReader_h
  