pxmlw6n2f/sdformat_for_mpi/include/sdf/Element.hh

384 lines
13 KiB
C++
Raw Normal View History

2019-04-26 11:20:11 +08:00
/*
* Copyright 2015 Open Source Robotics Foundation
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 _SDF_ELEMENT_HH_
#define _SDF_ELEMENT_HH_
#include <string>
#include <vector>
#include <memory>
#include "sdf/Param.hh"
#include "sdf/system_util.hh"
/// \todo Remove this diagnositic push/pop in version 5
#ifndef _WIN32
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#include "sdf/Types.hh"
#ifndef _WIN32
#pragma GCC diagnostic pop
#endif
#ifdef _WIN32
// Disable warning C4251 which is triggered by
// std::enable_shared_from_this
#pragma warning(push)
#pragma warning(disable: 4251)
#endif
/// \ingroup sdf_parser
/// \brief namespace for Simulation Description Format parser
namespace sdf
{
class ElementPrivate;
class SDFORMAT_VISIBLE Element;
/// \def ElementPtr
/// \brief Shared pointer to an SDF Element
typedef std::shared_ptr<Element> ElementPtr;
/// \def ElementWeakPtr
/// \brief Weak pointer to an SDF Element
typedef std::weak_ptr<Element> ElementWeakPtr;
/// \def ElementPtr_V
/// \brief Vector of ElementPtr
typedef std::vector<ElementPtr> ElementPtr_V;
/// \addtogroup sdf
/// \{
/// \class Element Element.hh sdf/sdf.hh
/// \brief SDF Element class
class SDFORMAT_VISIBLE Element :
public std::enable_shared_from_this<Element>
{
/// \brief Constructor.
public: Element();
/// \brief Destructor.
public: virtual ~Element();
/// \brief Create a copy of this Element.
/// \return A copy of this Element.
public: ElementPtr Clone() const;
/// \brief Copy values from an Element.
/// \param[in] _elem Element to copy value from.
public: void Copy(const ElementPtr _elem);
/// \brief Get a pointer to this Element's parent.
/// \return Pointer to this Element's parent, NULL if there is no
/// parent.
public: ElementPtr GetParent() const;
/// \brief Set the parent of this Element.
/// \param[in] _parent Paren for this element.
public: void SetParent(const ElementPtr _parent);
/// \brief Set the name of the Element.
/// \param[in] _name The new name for this Element.
public: void SetName(const std::string &_name);
/// \brief Get the Element's name.
/// \return The name of this Element.
public: const std::string &GetName() const;
/// \brief Set the requirement type.
/// \param[in] _req Requirement type for this element:
/// 0: Not required
/// 1: Exactly one element is required
/// +: One or more elements are required
/// *: Zero or more elements are required.
public: void SetRequired(const std::string &_req);
/// \brief Get the requirement string.
/// \return The requirement string.
/// \sa Element::SetRequired
public: const std::string &GetRequired() const;
/// \brief Set whether this element should copy its child elements
/// during parsing.
/// \param[in] _value True to copy Element's children.
public: void SetCopyChildren(bool _value);
/// \brief Return true if this Element's child elements should be copied
/// during parsing.
/// \return True to copy child elements during parsing.
public: bool GetCopyChildren() const;
/// \brief Set reference SDF element.
/// \param[in] _value Name of the reference sdf element.
public: void SetReferenceSDF(const std::string &_value);
/// \brief Get the name of the reference SDF element.
/// \return Name of the reference SDF element.
public: std::string ReferenceSDF() const;
/// \brief Output Element's description to stdout.
/// \param[in] _prefix String value to prefix to the output.
public: void PrintDescription(const std::string &_prefix);
/// \brief Output Element's values to stdout.
/// \param[in] _prefix String value to prefix to the output.
public: void PrintValues(std::string _prefix);
public: void PrintWiki(std::string _prefix);
/// \brief Helper function for SDF::PrintDoc
///
/// This generates the SDF html documentation.
/// \param[out] _html Accumulated HTML for output.
/// \param[in] _spacing Amount of spacing for this element.
/// \param[in] _index Unique index for this element.
public: void PrintDocLeftPane(std::string &_html,
int _spacing, int &_index);
/// \brief Helper function for SDF::PrintDoc
///
/// This generates the SDF html documentation.
/// \param[out] _html Accumulated HTML for output
/// \param[in] _spacing Amount of spacing for this element.
public: void PrintDocRightPane(std::string &_html,
int _spacing, int &_index);
/// \brief Convert the element values to a string representation.
/// \param[in] _prefix String value to prefix to the output.
/// \return The string representation.
public: std::string ToString(const std::string &_prefix) const;
/// \brief Add an attribute value.
/// \param[in] _key Key value.
/// \param[in] _type Type of data the attribute will hold.
/// \param[in] _defaultValue Default value for the attribute.
/// \param[in] _required Requirement string. \as Element::SetRequired.
/// \param[in] _description A text description of the attribute.
public: void AddAttribute(const std::string &_key,
const std::string &_type,
const std::string &_defaultvalue,
bool _required,
const std::string &_description="");
/// \brief Add a value to this Element.
/// \param[in] _type Type of data the attribute will hold.
/// \param[in] _defaultValue Default value for the attribute.
/// \param[in] _required Requirement string. \as Element::SetRequired.
/// \param[in] _description A text description of the attribute.
public: void AddValue(const std::string &_type,
const std::string &_defaultValue, bool _required,
const std::string &_description="");
/// \brief Get the param of an attribute.
/// \param[in] _key the name of the attribute
/// \return The parameter attribute value. NULL if the key is invalid.
public: ParamPtr GetAttribute(const std::string &_key);
/// \brief Get the number of attributes
public: size_t GetAttributeCount() const;
/// \brief Get an attribute using an index
public: ParamPtr GetAttribute(unsigned int _index) const;
/// \brief Get the number of element descriptions
public: size_t GetElementDescriptionCount() const;
/// \brief Get an element description using an index
public: ElementPtr GetElementDescription(unsigned int _index) const;
/// \brief Get an element descriptio using a key
public: ElementPtr GetElementDescription(const std::string &_key) const;
/// \brief Return true if an element description exists
public: bool HasElementDescription(const std::string &_name);
public: bool HasAttribute(const std::string &_key);
/// \brief Return true if the attribute was set (i.e. not default value)
public: bool GetAttributeSet(const std::string &_key);
/// \brief Get the param of the elements value
public: ParamPtr GetValue();
/// \brief Get the element value/attribute as a boost::any.
/// \param[in] _key The key of the attribute. If empty, get the value of
/// the element. Defaults to empty.
/// \return The element as a boost::any.
public: boost::any GetAny(const std::string &_key = "");
public: template<typename T>
T Get(const std::string &_key = "");
public: template<typename T>
bool Set(const T &_value);
public: bool HasElement(const std::string &_name) const;
public: ElementPtr GetElement(const std::string &_name) const;
/// \brief Get the first child element
/// \returns A smart pointer to the first child of this element, or
/// sdf::ElementPtr(nullptr) if there are no children
public: ElementPtr GetFirstElement() const;
/// \brief Get the next sibling of this element
/// \param[in] _name if given then filter siblings by their xml tag
/// \remarks This function does not alter or store any state
/// Repeated calls to "GetNextElement()" with the same string will
/// always return a pointer to the same element.
/// \returns the next sibling element or sdf::ElementPtr(nullptr)
///
/// This can be used in combination with GetFirstElement() to walk the SDF
/// tree. First call parent->GetFirstElement() to get the first child. Call
/// child = child->GetNextElement() to iterate through the children.
public: ElementPtr GetNextElement(const std::string &_name = "") const;
/// \brief Return a pointer to the child element with the provided name.
///
/// A new child element, with the provided name, is added to this element
/// if there is no existing child element.
/// \remarks If there are multiple elements with the given tag, it returns
/// the first one.
/// \param[in] _name Name of the child element to retreive.
/// \return Pointer to the existing child element, or a new child
/// element if an existing child element did not exist.
public: ElementPtr GetElement(const std::string &_name);
public: ElementPtr AddElement(const std::string &_name);
public: void InsertElement(ElementPtr _elem);
/// \brief Remove this element from its parent.
public: void RemoveFromParent();
/// \brief Remove a child element.
/// \param[in] _child Pointer to the child to remove.
public: void RemoveChild(ElementPtr _child);
/// \brief Remove all child elements.
public: void ClearElements();
public: void Update();
public: void Reset();
public: void SetInclude(const std::string &_filename);
public: std::string GetInclude() const;
/// \brief Get a text description of the element
public: std::string GetDescription() const;
/// \brief Set a text description for the element
public: void SetDescription(const std::string &_desc);
/// \brief Add a new element description
public: void AddElementDescription(ElementPtr _elem);
public: ElementPtr GetElementImpl(const std::string &_name) const;
private: void ToString(const std::string &_prefix,
std::ostringstream &_out) const;
private: ParamPtr CreateParam(const std::string &_key,
const std::string &_type, const std::string &_defaultValue,
bool _required, const std::string &_description="");
/// \brief Private data pointer
private: ElementPrivate *dataPtr;
};
/// \internal
/// \brief Private data for Element
class ElementPrivate
{
/// \brief Element name
public: std::string name;
/// \brief True if element is required
public: std::string required;
/// \brief Element description
public: std::string description;
/// \brief True if element's children should be copied.
public: bool copyChildren;
/// \brief Element's parent
public: ElementWeakPtr parent;
// Attributes of this element
public: Param_V attributes;
// Value of this element
public: ParamPtr value;
// The existing child elements
public: ElementPtr_V elements;
// The possible child elements
public: ElementPtr_V elementDescriptions;
/// name of the include file that was used to create this element
public: std::string includeFilename;
/// \brief Name of reference sdf.
public: std::string referenceSDF;
};
///////////////////////////////////////////////
template<typename T>
T Element::Get(const std::string &_key)
{
T result = T();
if (_key.empty() && this->dataPtr->value)
this->dataPtr->value->Get<T>(result);
else if (!_key.empty())
{
ParamPtr param = this->GetAttribute(_key);
if (param)
param->Get(result);
else if (this->HasElement(_key))
result = this->GetElementImpl(_key)->Get<T>();
else if (this->HasElementDescription(_key))
result = this->GetElementDescription(_key)->Get<T>();
else
sdferr << "Unable to find value for key[" << _key << "]\n";
}
return result;
}
///////////////////////////////////////////////
template<typename T>
bool Element::Set(const T &_value)
{
if (this->dataPtr->value)
{
this->dataPtr->value->Set(_value);
return true;
}
return false;
}
/// \}
}
#ifdef _WIN32
#pragma warning(pop)
#endif
#endif