384 lines
13 KiB
C++
384 lines
13 KiB
C++
|
/*
|
||
|
* 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
|