1// Author: Derek Barnett 2 3#include "pbbam/internal/DataSetElement.h" 4 5#include <iostream> 6 7namespace PacBio { 8namespace BAM { 9namespace internal { 10 11// ---------------- 12// DataSetElement 13// ---------------- 14 15inline DataSetElement::DataSetElement(const std::string& label, const XsdType& xsd) 16 : xsd_(xsd) 17 , label_(label) 18{ } 19 20inline DataSetElement::DataSetElement(const std::string& label, 21 const FromInputXml&, 22 const XsdType& xsd) 23 : xsd_(xsd) 24 , label_(label, true) 25{ } 26 27inline bool DataSetElement::operator==(const DataSetElement& other) const 28{ 29 return xsd_ == other.xsd_ && 30 label_ == other.label_ && 31 text_ == other.text_ && 32 attributes_ == other.attributes_ && 33 children_ == other.children_; 34} 35 36inline bool DataSetElement::operator!=(const DataSetElement& other) const 37{ return !(*this == other); } 38 39template<typename T> 40const T& DataSetElement::operator[](size_t index) const 41{ return Child<T>(index); } 42 43template<typename T> 44T& DataSetElement::operator[](size_t index) 45{ return Child<T>(index); } 46 47template<typename T> 48const T& DataSetElement::operator[](const std::string& label) const 49{ return Child<T>(label); } 50 51template<typename T> 52T& DataSetElement::operator[](const std::string& label) 53{ return Child<T>(label); } 54 55inline void DataSetElement::AddChild(const DataSetElement& e) 56{ children_.push_back(e); } 57 58inline std::string& DataSetElement::Attribute(const std::string& name) 59{ return attributes_[name]; } 60 61inline const std::string& DataSetElement::Attribute(const std::string& name) const 62{ 63 auto iter = attributes_.find(name); 64 if (iter == attributes_.cend()) 65 return SharedNullString(); 66 return iter->second; 67} 68 69inline void DataSetElement::Attribute(const std::string& name, const std::string& value) 70{ attributes_[name] = value; } 71 72inline const std::map<std::string, std::string>& DataSetElement::Attributes() const 73{ return attributes_; } 74 75inline std::map<std::string, std::string>& DataSetElement::Attributes() 76{ return attributes_; } 77 78template<typename T> 79inline const T& DataSetElement::Child(size_t index) const 80{ return static_cast<const T&>(children_.at(index)); } 81 82template<typename T> 83inline T& DataSetElement::Child(size_t index) 84{ return static_cast<T&>(children_.at(index)); } 85 86template<typename T> 87inline const T& DataSetElement::Child(const std::string& label) const 88{ return Child<T>(IndexOf(label)); } 89 90template<typename T> 91inline T& DataSetElement::Child(const std::string& label) 92{ 93 const int i = IndexOf(label); 94 if (i >= 0) { 95 assert(static_cast<size_t>(i) < NumChildren()); 96 return Child<T>(i); 97 } else { 98 AddChild(DataSetElement(label)); 99 return Child<T>(NumChildren()-1); 100 } 101} 102 103inline const std::vector<DataSetElement>& DataSetElement::Children() const 104{ return children_; } 105 106inline std::vector<DataSetElement>& DataSetElement::Children() 107{ return children_; } 108 109inline const std::string& DataSetElement::ChildText(const std::string& label) const 110{ 111 if (!HasChild(label)) 112 return SharedNullString(); 113 return Child<DataSetElement>(label).Text(); 114} 115 116inline std::string& DataSetElement::ChildText(const std::string& label) 117{ 118 if (!HasChild(label)) 119 AddChild(DataSetElement(label)); 120 return Child<DataSetElement>(label).Text(); 121} 122 123inline bool DataSetElement::HasAttribute(const std::string& name) const 124{ return attributes_.find(name) != attributes_.cend(); } 125 126inline bool DataSetElement::HasChild(const std::string& label) const 127{ return IndexOf(label) != -1; } 128 129inline int DataSetElement::IndexOf(const std::string& label) const 130{ 131 const size_t count = NumChildren(); 132 for (size_t i = 0; i < count; ++i) { 133 const DataSetElement& child = children_.at(i); 134 if (child.LocalNameLabel() == label || child.label_ == label) 135 return i; 136 } 137 return -1; 138} 139 140inline const boost::string_ref DataSetElement::LocalNameLabel() const 141{ return label_.LocalName(); } 142 143inline const boost::string_ref DataSetElement::PrefixLabel() const 144{ return label_.Prefix(); } 145 146inline const std::string& DataSetElement::QualifiedNameLabel() const 147{ return label_.QualifiedName(); } 148 149//inline std::string& DataSetElement::Label() 150//{ return label_.QualifiedName(); } 151 152inline void DataSetElement::Label(const std::string& label) 153{ label_ = XmlName(label, true); } 154 155inline size_t DataSetElement::NumAttributes() const 156{ return attributes_.size(); } 157 158inline size_t DataSetElement::NumChildren() const 159{ return children_.size(); } 160 161inline void DataSetElement::RemoveChild(const DataSetElement& e) 162{ 163 children_.erase( 164 std::remove(children_.begin(), 165 children_.end(), 166 e), 167 children_.end() 168 ); 169} 170 171inline void DataSetElement::ChildText(const std::string& label, 172 const std::string& text) 173{ 174 if (!HasChild(label)) { 175 DataSetElement e(label); 176 e.Text(text); 177 AddChild(e); 178 } else { 179 Child<DataSetElement>(label).Text(text); 180 } 181} 182 183inline bool DataSetElement::IsVerbatimLabel() const 184{ return label_.Verbatim(); } 185 186inline const std::string& DataSetElement::Text() const 187{ return text_; } 188 189inline std::string& DataSetElement::Text() 190{ return text_; } 191 192inline void DataSetElement::Text(const std::string& text) 193{ text_ = text; } 194 195inline const XsdType& DataSetElement::Xsd() const 196{ return xsd_; } 197 198// ---------------- 199// XmlName 200// ---------------- 201 202inline XmlName::XmlName(std::string fullName, bool verbatim) 203 : qualifiedName_(std::move(fullName)) 204 , prefixSize_(0) 205 , localNameOffset_(0) 206 , localNameSize_(0) 207 , verbatim_(verbatim) 208{ 209 const size_t colonFound = qualifiedName_.find(':'); 210 if (colonFound == std::string::npos || colonFound == 0) 211 localNameSize_ = qualifiedName_.size(); 212 else { 213 prefixSize_ = colonFound; 214 localNameSize_ = (qualifiedName_.size() - colonFound) - 1; 215 } 216 217 // adjust for colon if prefix present 218 localNameOffset_ = prefixSize_; 219 if (prefixSize_ != 0) 220 ++localNameOffset_; 221} 222 223inline XmlName::XmlName(const std::string& localName, 224 const std::string& prefix) 225 : prefixSize_(prefix.size()) 226 , localNameOffset_(prefixSize_) 227 , localNameSize_(localName.size()) 228 , verbatim_(true) 229{ 230 qualifiedName_.clear(); 231 qualifiedName_.reserve(localNameSize_+ prefixSize_ + 1); 232 qualifiedName_.append(prefix); 233 if (!qualifiedName_.empty()) 234 qualifiedName_.append(1, ':'); 235 qualifiedName_.append(localName); 236 237 // adjust for colon if prefix present 238 if (prefixSize_ != 0) 239 ++localNameOffset_; 240} 241 242inline bool XmlName::operator==(const XmlName& other) const 243{ return qualifiedName_ == other.qualifiedName_; } 244 245inline bool XmlName::operator!=(const XmlName& other) const 246{ return !(*this == other); } 247 248inline const boost::string_ref XmlName::LocalName() const 249{ return boost::string_ref(qualifiedName_.data() + localNameOffset_, localNameSize_); } 250 251inline const boost::string_ref XmlName::Prefix() const 252{ return boost::string_ref(qualifiedName_.data(), prefixSize_); } 253 254inline const std::string& XmlName::QualifiedName() const 255{ return qualifiedName_; } 256 257inline bool XmlName::Verbatim() const 258{ return verbatim_; } 259 260} // namespace internal 261} // namespace BAM 262} // namespace PacBio 263