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