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