a494952eba89aab5ebd738242eae7a294cfee9d0
[shibboleth/xmltooling.git] / xmltooling / util / XMLObjectChildrenList.h
1 /*
2  *  Copyright 2001-2006 Internet2
3  * 
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 /**
18  * @file XMLObjectChildrenList.h
19  * 
20  * STL-compatible container wrapper
21  */
22
23 #if !defined(__xmltooling_list_h__)
24 #define __xmltooling_list_h__
25
26 #include <xmltooling/DOMCachingXMLObject.h>
27 #include <xmltooling/exceptions.h>
28
29 #define ListOf(type) xmltooling::XMLObjectChildrenList<type>
30
31 namespace xmltooling {
32
33     // Forward reference
34     template <class _Tx, class _Ty=XMLObject> class XMLObjectChildrenList;
35
36     /**
37      * STL iterator that mediates access to an iterator over typed XML children.
38      * @param _Ty   a bidrectional sequence of the subtype to iterate over
39      */
40     template <class _Ty>
41     class XMLObjectChildrenIterator
42     {
43         typename _Ty::iterator m_iter;
44         template <class _Tx, class _Tz> friend class XMLObjectChildrenList;
45     public:
46         typedef typename _Ty::iterator::iterator_category iterator_category;
47         typedef typename _Ty::iterator::value_type value_type;
48         typedef typename _Ty::iterator::reference reference;
49         typedef typename _Ty::iterator::pointer pointer;
50         typedef typename _Ty::const_iterator::reference const_reference;
51         typedef typename _Ty::const_iterator::pointer const_pointer;
52         typedef typename _Ty::iterator::difference_type difference_type;
53
54         XMLObjectChildrenIterator() {
55         }
56
57         XMLObjectChildrenIterator(typename _Ty::iterator iter) {
58             m_iter=iter;
59         }
60
61         const_reference operator*() const {
62             return *m_iter;
63         }
64
65         pointer operator->() const {
66             return (&**this);
67         }
68
69         XMLObjectChildrenIterator& operator++() {
70             // preincrement
71             ++m_iter;
72             return (*this);
73         }
74
75         XMLObjectChildrenIterator& operator--() {
76             // predecrement
77             --m_iter;
78             return (*this);
79         }
80
81         XMLObjectChildrenIterator operator++(int) {
82             // postincrement
83             XMLObjectChildrenIterator _Tmp = *this;
84             ++*this;
85             return (_Tmp);
86         }
87
88         XMLObjectChildrenIterator operator--(int) {
89             // postdecrement
90             XMLObjectChildrenIterator _Tmp = *this;
91             --*this;
92             return (_Tmp);
93         }
94
95         XMLObjectChildrenIterator& operator+=(difference_type _Off) {
96             // increment by integer
97             m_iter += _Off;
98             return (*this);
99         }
100
101         XMLObjectChildrenIterator operator+(difference_type _Off) const {
102             // return this + integer
103             XMLObjectChildrenIterator _Tmp = *this;
104             return (_Tmp += _Off);
105         }
106
107         XMLObjectChildrenIterator& operator-=(difference_type _Off) {
108             // decrement by integer
109             return (*this += -_Off);
110         }
111
112         XMLObjectChildrenIterator operator-(difference_type _Off) const {
113             // return this - integer
114             XMLObjectChildrenIterator _Tmp = *this;
115             return (_Tmp -= _Off);
116         }
117
118         difference_type operator-(const XMLObjectChildrenIterator& _Right) const {
119             // return difference of iterators
120             return m_iter - _Right.m_iter;
121         }
122
123         const_reference operator[](difference_type _Off) const {
124             // subscript
125             return (*(*this + _Off));
126         }
127
128         bool operator==(const XMLObjectChildrenIterator &_Right) const {
129                     // test for iterator equality
130                     return (m_iter == _Right.m_iter);
131             }
132
133             bool operator!=(const XMLObjectChildrenIterator &_Right) const {
134                     // test for iterator inequality
135                     return (!(m_iter == _Right.m_iter));
136             }
137     };
138
139     /**
140      * STL-compatible container that mediates access to underlying lists of typed XML children.
141      * @param _Tx   the subtype to expose a container over
142      * @param _Ty   the base type in the underlying list (defaults to XMLObject)
143      */
144     template <class _Tx, class _Ty>
145     class XMLObjectChildrenList
146     {
147         typedef typename std::vector<_Tx*> container;
148         typename XMLObjectChildrenList::container& m_vector;
149         typename std::list<_Ty*>& m_list;
150         typename std::list<_Ty*>::iterator m_fence;
151         XMLObject* m_parent;
152
153         public:
154         typedef typename container::value_type value_type;
155         typedef typename container::reference reference;
156         typedef typename container::const_reference const_reference;
157         typedef typename container::difference_type difference_type;
158         typedef typename container::size_type size_type;
159
160         // We override the iterator types with our constrained wrapper.
161         typedef XMLObjectChildrenIterator<typename XMLObjectChildrenList::container> iterator;
162         typedef const XMLObjectChildrenIterator<typename XMLObjectChildrenList::container> const_iterator;
163
164         /**
165          * Constructor to expose a typed collection of children backed by a list of a base type.
166          *
167          * @param parent    parent object of the collection
168          * @param v         underlying vector of iterators that reference the children
169          * @param backing   backing list for children
170          * @param ins_fence a marker designating where new children of this type should be added
171          */
172         XMLObjectChildrenList(
173             XMLObject* parent,
174             typename XMLObjectChildrenList::container& v,
175             typename std::list<_Ty*>& backing,
176             typename std::list<_Ty*>::iterator ins_fence
177             ) : m_parent(parent), m_vector(v), m_list(backing), m_fence(ins_fence) {
178         }
179
180         size_type size() const {
181             // return length of sequence
182             return m_vector.size();
183         }
184
185         bool empty() const {
186             // test if sequence is empty
187             return m_vector.empty();
188         }
189
190         iterator begin() {
191             // return iterator for beginning of mutable sequence
192             return m_vector.begin();
193         }
194
195         iterator end() {
196             // return iterator for end of mutable sequence
197             return m_vector.end();
198         }
199
200         const_iterator begin() const {
201             // return iterator for beginning of const sequence
202             return m_vector.begin();
203         }
204
205         const_iterator end() const {
206             // return iterator for end of const sequence
207             return m_vector.end();
208         }
209
210         const_reference at(size_type _Pos) const {
211             // subscript nonmutable sequence with checking
212             return m_vector.at(_Pos);
213         }
214
215         const_reference operator[](size_type _Pos) const {
216             // subscript nonmutable sequence
217             return m_vector[_Pos];
218         }
219
220         const_reference front() const {
221             // return first element of nonmutable sequence
222             return (*begin());
223         }
224
225         const_reference back() const {
226             // return last element of nonmutable sequence
227             return *(m_vector.back());
228         }
229
230         void push_back(const_reference _Val) {
231             setParent(_Val);
232             m_list.insert(m_fence,_Val);
233             m_vector.push_back(_Val);
234         }
235
236         iterator erase(iterator _Where) {
237             removeParent(*_Where);
238             removeChild(*_Where);
239             return m_vector.erase(_Where.m_iter);
240         }
241
242         iterator erase(iterator _First, iterator _Last) {
243             for (iterator i=_First; i!=_Last; i++) {
244                 removeParent(*i);
245                 removeChild(*i);
246             }
247             return m_vector.erase(_First,_Last);
248         }
249
250     private:
251         void setParent(const_reference _Val) {
252             if (_Val->getParent())
253                 throw XMLObjectException("Child object already has a parent.");
254             _Val->setParent(m_parent);
255             DOMCachingXMLObject* dc=dynamic_cast<DOMCachingXMLObject*>(_Val);
256             if (dc) {
257                 dc->releaseParentDOM(true);
258             }
259         }
260
261         void removeParent(const_reference _Val) {
262             if (_Val->getParent()!=m_parent)
263                 throw XMLObjectException("Child object not owned by this parent.");
264             _Val->setParent(NULL);
265             DOMCachingXMLObject* dc=dynamic_cast<DOMCachingXMLObject*>(m_parent);
266             if (dc) {
267                 dc->releaseParentDOM(true);
268             }
269         }
270
271         void removeChild(const_reference _Val) {
272             for (typename std::list<_Ty*>::iterator i=m_list.begin(); i!=m_list.end(); i++) {
273                 if ((*i)==_Val) {
274                     m_list.erase(i);
275                     delete _Val;
276                     return;
277                 }
278             }
279         }
280     };
281
282 };
283
284 #endif /* __xmltooling_list_h__ */