2 * Copyright 2001-2007 Internet2
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * @file XMLObjectChildrenList.h
20 * STL-compatible container wrapper
23 #ifndef __xmltooling_list_h__
24 #define __xmltooling_list_h__
26 #include <xmltooling/exceptions.h>
29 * Shorthand for an XMLObjectChildrenList wrapped around a vector
31 * @param type the type of object in the vector
33 #define VectorOf(type) xmltooling::XMLObjectChildrenList< std::vector<type*> >
36 * Shorthand for an XMLObjectChildrenList wrapped around a list
38 * @param type the type of object in the list
40 #define ListOf(type) xmltooling::XMLObjectChildrenList< std::list<type*> >
43 * Shorthand for an XMLObjectChildrenList wrapped around a deque
45 * @param type the type of object in the deque
47 #define DequeOf(type) xmltooling::XMLObjectChildrenList< std::deque<type*> >
50 * Shorthand for an XMLObjectPairList wrapped around a vector
52 * @param type1 the first type of object in the vector
53 * @param type2 the second type of object in the vector
55 #define VectorOfPairs(type1,type2) xmltooling::XMLObjectPairList< std::vector< std::pair<type1*,type2*> > >
58 * Shorthand for an XMLObjectPairList wrapped around a list
60 * @param type1 the first type of object in the vector
61 * @param type2 the second type of object in the vector
63 #define ListOfPairs(type1,type2) xmltooling::XMLObjectPairList< std::list< std::pair<type1*,type2*> > >
66 * Shorthand for an XMLObjectPairList wrapped around a deque
68 * @param type1 the first type of object in the vector
69 * @param type2 the second type of object in the vector
71 #define DequeOfPairs(type1,type2) xmltooling::XMLObjectPairList< std::deque< std::pair<type1*,type2*> > >
73 namespace xmltooling {
76 template <class _Tx, class _Ty=XMLObject> class XMLObjectChildrenList;
77 template <class _Tx, class _Ty=XMLObject> class XMLObjectPairList;
80 * STL iterator that mediates access to an iterator over typed XML children.
81 * @param _Ty a bidrectional sequence of the subtype to iterate over
84 class XMLObjectChildrenIterator
87 typename _Ty::iterator m_iter;
88 template <class _Tx, class _Tz> friend class XMLObjectChildrenList;
89 template <class _Tx, class _Tz> friend class XMLObjectPairList;
91 typedef typename _Ty::iterator::iterator_category iterator_category;
92 typedef typename _Ty::iterator::value_type value_type;
93 typedef typename _Ty::iterator::reference reference;
94 typedef typename _Ty::iterator::pointer pointer;
95 typedef typename _Ty::const_iterator::reference const_reference;
96 typedef typename _Ty::const_iterator::pointer const_pointer;
97 typedef typename _Ty::iterator::difference_type difference_type;
99 XMLObjectChildrenIterator() {
102 XMLObjectChildrenIterator(typename _Ty::iterator iter) {
106 const_reference operator*() const {
110 const_reference operator->() const {
111 return *(m_iter.operator->());
114 XMLObjectChildrenIterator& operator++() {
120 XMLObjectChildrenIterator& operator--() {
126 XMLObjectChildrenIterator operator++(int) {
128 XMLObjectChildrenIterator _Tmp = *this;
133 XMLObjectChildrenIterator operator--(int) {
135 XMLObjectChildrenIterator _Tmp = *this;
140 XMLObjectChildrenIterator& operator+=(difference_type _Off) {
141 // increment by integer
146 XMLObjectChildrenIterator operator+(difference_type _Off) const {
147 // return this + integer
148 return m_iter + _Off;
151 XMLObjectChildrenIterator& operator-=(difference_type _Off) {
152 // decrement by integer
153 return (*this += -_Off);
156 XMLObjectChildrenIterator operator-(difference_type _Off) const {
157 // return this - integer
158 XMLObjectChildrenIterator _Tmp = *this;
159 return (_Tmp -= _Off);
162 difference_type operator-(const XMLObjectChildrenIterator& _Right) const {
163 // return difference of iterators
164 return m_iter - _Right.m_iter;
167 const_reference operator[](difference_type _Off) const {
169 return (*(*this + _Off));
172 bool operator==(const XMLObjectChildrenIterator &_Right) const {
173 // test for iterator equality
174 return (m_iter == _Right.m_iter);
177 bool operator!=(const XMLObjectChildrenIterator &_Right) const {
178 // test for iterator inequality
179 return (!(m_iter == _Right.m_iter));
185 * STL-compatible container that mediates access to underlying lists of typed XML children.
186 * @param _Tx the subtype container to encapsulate
187 * @param _Ty the base type in the underlying list (defaults to XMLObject)
189 template <class Container, class _Ty>
190 class XMLObjectChildrenList
192 Container& m_container;
193 typename std::list<_Ty*>* m_list;
194 typename std::list<_Ty*>::iterator m_fence;
199 typedef typename Container::value_type value_type;
200 typedef typename Container::reference reference;
201 typedef typename Container::const_reference const_reference;
202 typedef typename Container::difference_type difference_type;
203 typedef typename Container::size_type size_type;
205 // We override the iterator types with our constrained wrapper.
206 typedef XMLObjectChildrenIterator<Container> iterator;
207 typedef XMLObjectChildrenIterator<Container> const_iterator;
211 * Constructor to expose a typed collection of children backed by a list of a base type.
213 * @param parent parent object of the collection
214 * @param sublist underlying container to expose
215 * @param backing pointer to backing list for children, if any
216 * @param ins_fence a marker designating where new children of this type should be added
218 XMLObjectChildrenList(
221 typename std::list<_Ty*>* backing,
222 typename std::list<_Ty*>::iterator ins_fence
223 ) : m_container(sublist), m_list(backing), m_fence(ins_fence), m_parent(parent) {
228 size_type size() const {
229 // return length of sequence
230 return m_container.size();
234 // test if sequence is empty
235 return m_container.empty();
239 // return iterator for beginning of mutable sequence
240 return m_container.begin();
244 // return iterator for end of mutable sequence
245 return m_container.end();
248 const_iterator begin() const {
249 // return iterator for beginning of const sequence
250 return m_container.begin();
253 const_iterator end() const {
254 // return iterator for end of const sequence
255 return m_container.end();
258 const_reference at(size_type _Pos) const {
259 // subscript nonmutable sequence with checking
260 return m_container.at(_Pos);
263 const_reference operator[](size_type _Pos) const {
264 // subscript nonmutable sequence
265 return m_container[_Pos];
268 const_reference front() const {
269 // return first element of nonmutable sequence
270 return m_container.front();
273 const_reference back() const {
274 // return last element of nonmutable sequence
275 return m_container.back();
278 void push_back(const_reference _Val) {
281 m_list->insert(m_fence,_Val);
282 m_container.push_back(_Val);
285 iterator erase(iterator _Where) {
286 removeParent(*_Where);
288 removeChild(*_Where);
290 delete *_Where.m_iter;
291 return m_container.erase(_Where.m_iter);
294 iterator erase(iterator _First, iterator _Last) {
295 for (iterator i=_First; i!=_Last; i++) {
302 return m_container.erase(_First.m_iter,_Last.m_iter);
306 erase(begin(),end());
310 void setParent(const_reference _Val) {
311 if (_Val->getParent())
312 throw XMLObjectException("Child object already has a parent.");
313 _Val->setParent(m_parent);
314 _Val->releaseParentDOM(true);
317 void removeParent(const_reference _Val) {
318 if (_Val->getParent()!=m_parent)
319 throw XMLObjectException("Child object not owned by this parent.");
320 _Val->setParent(NULL);
321 m_parent->releaseParentDOM(true);
324 void removeChild(const_reference _Val) {
325 for (typename std::list<_Ty*>::iterator i=m_list->begin(); i!=m_list->end(); i++) {
337 * STL-compatible container that mediates access to underlying lists of typed XML children
338 * that come in pairs.
340 * @param _Tx the subtype container to encapsulate
341 * @param _Ty the base type in the underlying list (defaults to XMLObject)
343 template <class Container, class _Ty>
344 class XMLObjectPairList
346 Container& m_container;
347 typename std::list<_Ty*>* m_list;
348 typename std::list<_Ty*>::iterator m_fence;
353 typedef typename Container::value_type value_type;
354 typedef typename Container::reference reference;
355 typedef typename Container::const_reference const_reference;
356 typedef typename Container::difference_type difference_type;
357 typedef typename Container::size_type size_type;
359 // We override the iterator types with our constrained wrapper.
360 typedef XMLObjectChildrenIterator<Container> iterator;
361 typedef XMLObjectChildrenIterator<Container> const_iterator;
365 * Constructor to expose a typed collection of pairs backed by a list of a base type.
367 * @param parent parent object of the collection
368 * @param sublist underlying container to expose
369 * @param backing pointer to backing list for children, if any
370 * @param ins_fence a marker designating where new children of this type should be added
375 typename std::list<_Ty*>* backing,
376 typename std::list<_Ty*>::iterator ins_fence
377 ) : m_container(sublist), m_list(backing), m_fence(ins_fence), m_parent(parent) {
382 size_type size() const {
383 // return length of sequence
384 return m_container.size();
388 // test if sequence is empty
389 return m_container.empty();
393 // return iterator for beginning of mutable sequence
394 return m_container.begin();
398 // return iterator for end of mutable sequence
399 return m_container.end();
402 const_iterator begin() const {
403 // return iterator for beginning of const sequence
404 return m_container.begin();
407 const_iterator end() const {
408 // return iterator for end of const sequence
409 return m_container.end();
412 const_reference at(size_type _Pos) const {
413 // subscript nonmutable sequence with checking
414 return m_container.at(_Pos);
417 const_reference operator[](size_type _Pos) const {
418 // subscript nonmutable sequence
419 return m_container[_Pos];
422 const_reference front() const {
423 // return first element of nonmutable sequence
424 return m_container.front();
427 const_reference back() const {
428 // return last element of nonmutable sequence
429 return m_container.back();
432 void push_back(const_reference _Val) {
435 m_list->insert(m_fence,_Val.first);
436 m_list->insert(m_fence,_Val.second);
438 m_container.push_back(_Val);
441 iterator erase(iterator _Where) {
442 removeParent(*_Where);
444 removeChild(*_Where);
446 delete _Where.m_iter->first;
447 delete _Where.m_iter->second;
449 return m_container.erase(_Where.m_iter);
452 iterator erase(iterator _First, iterator _Last) {
453 for (iterator i=_First; i!=_Last; i++) {
458 delete i.m_iter->first;
459 delete i.m_iter->second;
462 return m_container.erase(_First,_Last);
466 erase(begin(),end());
470 void setParent(const_reference _Val) {
471 if (_Val.first->getParent() || (_Val.second && _Val.second->getParent()))
472 throw XMLObjectException("One of the child objects already has a parent.");
473 _Val.first->setParent(m_parent);
475 _Val.second->setParent(m_parent);
476 _Val.first->releaseParentDOM(true);
479 void removeParent(const_reference _Val) {
480 if (_Val.first->getParent()!=m_parent || (_Val.second && _Val.second->getParent()!=m_parent))
481 throw XMLObjectException("One of the child objects not owned by this parent.");
482 _Val.first->setParent(NULL);
484 _Val.second->setParent(NULL);
485 m_parent->releaseParentDOM(true);
488 void removeChild(const_reference _Val) {
489 for (typename std::list<_Ty*>::iterator i=m_list->begin(); i!=m_list->end(); i++) {
490 if ((*i)==_Val.first) {
491 typename std::list<_Ty*>::iterator j=i++;
506 #endif /* __xmltooling_list_h__ */