Skip to content
Snippets Groups Projects
  • Nick Draper's avatar
    ef3ccb58
    Merge pull request #23693 from mantidproject/23488_update_file_headers · ef3ccb58
    Nick Draper authored
    Update copyright headers in all files
    
    Squashed commit of the following:
    
    * First version of a script to manage copyright statements
    
    re #23468
    
    * Neatened up script, added comments
    
    re #23488
    
    * move script to tools directory
    
    re #23488
    
    * small script changes and a couple of manual file changes
    
    re #23488
    
    * Minor chnage to whitespace detection in regex
    
    re #23488
    
    * Add an excluded directory
    
    re #23488
    
    * remove a repeasted copyright statement in a file
    
    re #23488
    
    * Don't comsume the comment end if it is on the same line
    
    re #23488
    
    * fix error in new copright parsing
    
    re #23488
    
    * remove double copyrifght entry
    
    re #23488
    
    * Improve handling of old copyrights at the start of comments
    
    re #23488
    
    * remove empty comments re #23488
    
    * exclude gsoapgenerated directories
    
    re #23488
    
    * Sort out greedy line matching re #23488
    
    * improve empty comment removal
    
    re #23488
    
    * improve false positives
    
    re #23488
    
    * impressive speedup by limiting regex matching length
    
    re #23488
    
    * remove evil invisible non ascii character
    
    Also upadte the copyright at the same time
    
    re #23488
    
    * resolve multiple copyrights in a single file
    
    re #23488
    
    * resolve an issue with new statement detection
    
    re #23488
    
    * another unprintable unicode character
    
    re #23488
    
    * pep updates and cmake the new copyright fit clang format
    
    re #23488
    
    * update already done new format headers
    
    re #23488
    
    * wrong type of bracket
    
    re #23488
    
    * Update class_maker and friends
    
    re #23488
    
    * Update all copyright statements
    
    re #23488
    
    * clang format re #23488
    
    * flake8 warnings re #23488
    
    * Flake8 warnings re #23488
    
    * Exclude .cmake.in and rb.in files
    
    re #23488
    
    * replace missing line re #23488
    
    * exclude .py.in files as they are flasely recognized as C++
    
    re #23488
    
    * another setp.py.in re #23488
    
    * another .py.in correction re #23488
    
    * Hopefully the last of the .py.in files re #23488
    
    * resolve utf-8 encoding of python files and changed ABINS checksum
    
    re #23488
    
    * updates to unit tests that reference line numbers
    
    re #23488
    
    * remaining unit test files and other fixes
    
    re #23488
    ef3ccb58
    History
    Merge pull request #23693 from mantidproject/23488_update_file_headers
    Nick Draper authored
    Update copyright headers in all files
    
    Squashed commit of the following:
    
    * First version of a script to manage copyright statements
    
    re #23468
    
    * Neatened up script, added comments
    
    re #23488
    
    * move script to tools directory
    
    re #23488
    
    * small script changes and a couple of manual file changes
    
    re #23488
    
    * Minor chnage to whitespace detection in regex
    
    re #23488
    
    * Add an excluded directory
    
    re #23488
    
    * remove a repeasted copyright statement in a file
    
    re #23488
    
    * Don't comsume the comment end if it is on the same line
    
    re #23488
    
    * fix error in new copright parsing
    
    re #23488
    
    * remove double copyrifght entry
    
    re #23488
    
    * Improve handling of old copyrights at the start of comments
    
    re #23488
    
    * remove empty comments re #23488
    
    * exclude gsoapgenerated directories
    
    re #23488
    
    * Sort out greedy line matching re #23488
    
    * improve empty comment removal
    
    re #23488
    
    * improve false positives
    
    re #23488
    
    * impressive speedup by limiting regex matching length
    
    re #23488
    
    * remove evil invisible non ascii character
    
    Also upadte the copyright at the same time
    
    re #23488
    
    * resolve multiple copyrights in a single file
    
    re #23488
    
    * resolve an issue with new statement detection
    
    re #23488
    
    * another unprintable unicode character
    
    re #23488
    
    * pep updates and cmake the new copyright fit clang format
    
    re #23488
    
    * update already done new format headers
    
    re #23488
    
    * wrong type of bracket
    
    re #23488
    
    * Update class_maker and friends
    
    re #23488
    
    * Update all copyright statements
    
    re #23488
    
    * clang format re #23488
    
    * flake8 warnings re #23488
    
    * Flake8 warnings re #23488
    
    * Exclude .cmake.in and rb.in files
    
    re #23488
    
    * replace missing line re #23488
    
    * exclude .py.in files as they are flasely recognized as C++
    
    re #23488
    
    * another setp.py.in re #23488
    
    * another .py.in correction re #23488
    
    * Hopefully the last of the .py.in files re #23488
    
    * resolve utf-8 encoding of python files and changed ABINS checksum
    
    re #23488
    
    * updates to unit tests that reference line numbers
    
    re #23488
    
    * remaining unit test files and other fixes
    
    re #23488
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
InstrumentInfo.cpp 10.03 KiB
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
//     NScD Oak Ridge National Laboratory, European Spallation Source
//     & Institut Laue - Langevin
// SPDX - License - Identifier: GPL - 3.0 +
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include <algorithm>

#include "MantidKernel/FacilityInfo.h"
#include "MantidKernel/InstrumentInfo.h"
#include "MantidKernel/Logger.h"
#include "MantidKernel/Strings.h"

#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>

#include <Poco/AutoPtr.h>
#include <Poco/DOM/Element.h>
#include <Poco/DOM/NodeList.h>
#include <Poco/DOM/Text.h>

namespace Mantid {
namespace Kernel {
namespace {
// static logger object
Logger g_log("InstrumentInfo");
} // namespace

/** Constructor.
 * @param f :: The facility
 * @param elem :: The Poco::XML::Element to read the data from
 * @throw std::runtime_error if name or at least one technique are not defined
 */
InstrumentInfo::InstrumentInfo(const FacilityInfo *f,
                               const Poco::XML::Element *elem)
    : m_facility(f) {

  m_name = elem->getAttribute("name");
  if (m_name.empty()) {
    throw std::runtime_error("Instrument name is not defined");
  }

  // The string to separate the instrument name and the run number.
  m_delimiter = elem->getAttribute("delimiter");
  if (m_delimiter.empty()) {
    m_delimiter = f->delimiter();
  }

  m_shortName = elem->getAttribute("shortname");
  if (m_shortName.empty()) {
    m_shortName = m_name;
  }

  fillTechniques(elem);
  fillLiveData(elem);
  fillZeroPadding(elem);
}

/**
 * Equality operator. Two objects are considered equal if their names and short
 * names are the same.
 * @param rhs :: The object to compare this with
 * @returns True if the objects are considered equal, false otherwise
 */
bool InstrumentInfo::operator==(const InstrumentInfo &rhs) const {
  return (this->name() == rhs.name() && this->shortName() == rhs.shortName());
}

/// Returns the default delimiter between instrument name and run number
std::string InstrumentInfo::delimiter() const { return m_delimiter; }

/// Return the name of the instrument
const std::string InstrumentInfo::name() const { return m_name; }

/// Return the short name of the instrument
const std::string InstrumentInfo::shortName() const { return m_shortName; }

/// Returns zero padding for this instrument
int InstrumentInfo::zeroPadding(unsigned int runNumber) const {
  if (m_zeroPadding.empty())
    return m_facility->zeroPadding();
  if (m_zeroPadding.size() == 1) {
    auto padding = m_zeroPadding.begin();
    if (runNumber >= padding->first)
      return getZeroPadding(padding);
    else
      return m_facility->zeroPadding();
  }
  auto last = m_zeroPadding.end();
  --last;
  for (auto it = m_zeroPadding.begin(); it != last; ++it) {
    auto next = it;
    ++next;
    if (runNumber >= it->first && runNumber < next->first) {
      return getZeroPadding(it);
    }
  }
  return getZeroPadding(last);
}

/**
 * Returns file prefix for this instrument and a run number.
 * @param runNumber :: A run number.
 */
std::string InstrumentInfo::filePrefix(unsigned int runNumber) const {
  if (m_zeroPadding.empty())
    return m_shortName;
  if (m_zeroPadding.size() == 1) {
    auto padding = m_zeroPadding.begin();
    if (runNumber >= padding->first)
      return getPrefix(padding);
    else
      return m_shortName;
  }
  auto last = m_zeroPadding.end();
  --last;
  for (auto it = m_zeroPadding.begin(); it != last; ++it) {
    auto next = it;
    ++next;
    if (runNumber >= it->first && runNumber < next->first) {
      return getPrefix(it);
    }
  }
  return getPrefix(last);
}

/// Returns the name of the live listener
std::string InstrumentInfo::liveListener(const std::string &name) const {
  if (!hasLiveListenerInfo())
    return "";

  return liveListenerInfo(name).listener();
}

/** Returns the host & port to connect to for a live data stream
 *  No guarantees are given that the provided string is well-formed and valid
 *    - the caller should check this themselves
 */
std::string InstrumentInfo::liveDataAddress(const std::string &name) const {
  if (!hasLiveListenerInfo())
    return "";

  return liveListenerInfo(name).address();
}

/**
 * Get LiveListenerInfo for specified connection (or default).
 *
 * @param name Name attribute of connection to return info on
 * @return Reference to LiveListenerInfo for specified connection
 * @throw std::runtime_error When no listeners, or name not found
 */
const LiveListenerInfo &
InstrumentInfo::liveListenerInfo(std::string name) const {
  if (!hasLiveListenerInfo())
    throw std::runtime_error("Attempted to access live listener for " + m_name +
                             " instrument, which has no listeners.");

  // Default to specified default connection
  if (name.empty())
    name = m_defaultListener;

  // If no default connection specified, fallback to first connection
  if (name.empty())
    return m_listeners.front();

  // Name specified, find requested connection
  for (auto &listener : m_listeners) {
    // Names are compared case insensitively
    if (boost::iequals(listener.name(), name))
      return listener;
  }

  // The provided name was not valid / did not match any listeners
  throw std::runtime_error("Could not find connection " + name +
                           " for instrument " + m_name);
}

bool InstrumentInfo::hasLiveListenerInfo() const {
  return !m_listeners.empty();
}

const std::vector<LiveListenerInfo> &
InstrumentInfo::liveListenerInfoList() const {
  return m_listeners;
}

/// Return list of techniques
const std::set<std::string> &InstrumentInfo::techniques() const {
  return m_technique;
}

/// Return the facility
const FacilityInfo &InstrumentInfo::facility() const { return *m_facility; }

/// Called from constructor to fill zero padding
void InstrumentInfo::fillZeroPadding(const Poco::XML::Element *elem) {
  Poco::AutoPtr<Poco::XML::NodeList> pNL_zeropadding =
      elem->getElementsByTagName("zeropadding");
  unsigned long n = pNL_zeropadding->length();

  for (unsigned long i = 0; i < n; ++i) {
    auto elem = dynamic_cast<Poco::XML::Element *>(pNL_zeropadding->item(i));
    if (!elem)
      continue;
    // read the zero padding size
    if (!elem->hasAttribute("size")) {
      throw std::runtime_error("Zeropadding size is missing for instrument " +
                               m_name);
    }
    auto &sizeStr = elem->getAttribute("size");
    int size = 0;
    if (!Mantid::Kernel::Strings::convert(sizeStr, size)) {
      throw std::runtime_error(
          "Zeropadding size must be an integer value (instrument " + m_name +
          ")");
    }
    // read the start run number
    unsigned int startRunNumber = 0;
    if (!elem->hasAttribute("startRunNumber")) {
      if (!m_zeroPadding.empty()) {
        throw std::runtime_error("Zeropadding size is missing for instrument " +
                                 m_name);
      }
    } else {
      auto &startRunNumberStr = elem->getAttribute("startRunNumber");
      try {
        startRunNumber = boost::lexical_cast<unsigned int>(startRunNumberStr);
      } catch (...) {
        throw std::runtime_error("Zeropadding start run number must be an "
                                 "integer value (instrument " +
                                 m_name + ")");
      }
    }
    // read the file prefix
    std::string prefix = m_shortName;
    if (elem->hasAttribute("prefix")) {
      prefix = elem->getAttribute("prefix");
    }
    m_zeroPadding[startRunNumber] = std::make_pair(prefix, size);
  }

  if (m_zeroPadding.empty()) {
    m_zeroPadding[0] = std::make_pair(m_shortName, m_facility->zeroPadding());
  }
}

/// Called from constructor to fill live listener name
void InstrumentInfo::fillTechniques(const Poco::XML::Element *elem) {
  Poco::AutoPtr<Poco::XML::NodeList> pNL_technique =
      elem->getElementsByTagName("technique");
  unsigned long n = pNL_technique->length();

  for (unsigned long i = 0; i < n; ++i) {
    Poco::AutoPtr<Poco::XML::NodeList> pNL =
        pNL_technique->item(i)->childNodes();
    if (pNL->length() > 0) {
      Poco::XML::Text *txt = dynamic_cast<Poco::XML::Text *>(pNL->item(0));
      if (txt) {
        const std::string &tech = txt->getData();
        if (!tech.empty()) {
          m_technique.insert(tech);
        }
      }
    }
  }

  if (m_technique.empty()) {
    throw std::runtime_error("No technique is defined for instrument " +
                             m_name);
  }
}

/// Called from constructor to fill live listener name
void InstrumentInfo::fillLiveData(const Poco::XML::Element *elem) {
  // See if we have a <livedata> element (will be NULL if there's none)
  Poco::XML::Element *live = elem->getChildElement("livedata");
  if (!live)
    return;

  // Load default connection name attribute
  m_defaultListener = live->getAttribute("default");

  // Get connections under <livedata>
  Poco::AutoPtr<Poco::XML::NodeList> connections =
      elem->getElementsByTagName("connection");

  // Load connection info for each child element
  for (unsigned long i = 0; i < connections->length(); ++i) {
    auto *conn = dynamic_cast<Poco::XML::Element *>(connections->item(i));
    try {
      m_listeners.emplace_back(this, conn);
    } catch (...) {
      g_log.error() << "Exception occurred while loading livedata for "
                    << m_name << " instrument. Skipping faulty connection.\n";
    }
  }
}

//-------------------------------------------------------------------------
// Non-member functions
//-------------------------------------------------------------------------
/**
 * Prints the instrument name to the stream
 * @param buffer :: A reference to an output stream
 * @param instrumentDescriptor :: A reference to an InstrumentInfo object
 * @return A reference to the stream written to
 */
std::ostream &operator<<(std::ostream &buffer,
                         const InstrumentInfo &instrumentDescriptor) {
  buffer << instrumentDescriptor.name();
  return buffer;
}

} // namespace Kernel
} // namespace Mantid