First cut at signing support.
[shibboleth/cpp-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             return m_iter + _Off;
106         }
107
108         XMLObjectChildrenIterator& operator-=(difference_type _Off) {
109             // decrement by integer
110             return (*this += -_Off);
111         }
112
113         XMLObjectChildrenIterator operator-(difference_type _Off) const {
114             // return this - integer
115             XMLObjectChildrenIterator _Tmp = *this;
116             return (_Tmp -= _Off);
117         }
118
119         difference_type operator-(const XMLObjectChildrenIterator& _Right) const {
120             // return difference of iterators
121             return m_iter - _Right.m_iter;
122         }
123
124         const_reference operator[](difference_type _Off) const {
125             // subscript
126             return (*(*this + _Off));
127         }
128
129         bool operator==(const XMLObjectChildrenIterator &_Right) const {
130                     // test for iterator equality
131                     return (m_iter == _Right.m_iter);
132             }
133
134             bool operator!=(const XMLObjectChildrenIterator &_Right) const {
135                     // test for iterator inequality
136                     return (!(m_iter == _Right.m_iter));
137             }
138     };
139
140     /**
141      * STL-compatible container that mediates access to underlying lists of typed XML children.
142      * @param _Tx   the subtype container to encapsulate
143      * @param _Ty   the base type in the underlying list (defaults to XMLObject)
144      */
145     template <class Container, class _Ty>
146     class XMLObjectChildrenList
147     {
148         Container& m_container;
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<Container> iterator;
162         typedef XMLObjectChildrenIterator<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 sublist   underlying container to expose
169          * @param backing   pointer to backing list for children, if any
170          * @param ins_fence a marker designating where new children of this type should be added
171          */
172         XMLObjectChildrenList(
173             XMLObject* parent,
174             Container& sublist,
175             typename std::list<_Ty*>* backing,
176             typename std::list<_Ty*>::iterator ins_fence
177             ) : m_parent(parent), m_container(sublist), m_list(backing), m_fence(ins_fence) {
178         }
179
180         size_type size() const {
181             // return length of sequence
182             return m_container.size();
183         }
184
185         bool empty() const {
186             // test if sequence is empty
187             return m_container.empty();
188         }
189
190         iterator begin() {
191             // return iterator for beginning of mutable sequence
192             return m_container.begin();
193         }
194
195         iterator end() {
196             // return iterator for end of mutable sequence
197             return m_container.end();
198         }
199
200         const_iterator begin() const {
201             // return iterator for beginning of const sequence
202             return m_container.begin();
203         }
204
205         const_iterator end() const {
206             // return iterator for end of const sequence
207             return m_container.end();
208         }
209
210         const_reference at(size_type _Pos) const {
211             // subscript nonmutable sequence with checking
212             return m_container.at(_Pos);
213         }
214
215         const_reference operator[](size_type _Pos) const {
216             // subscript nonmutable sequence
217             return m_container[_Pos];
218         }
219
220         const_reference front() const {
221             // return first element of nonmutable sequence
222             return m_container.front();
223         }
224
225         const_reference back() const {
226             // return last element of nonmutable sequence
227             return m_container.back();
228         }
229
230         void push_back(const_reference _Val) {
231             setParent(_Val);
232             if (m_list)
233                 m_list->insert(m_fence,_Val);
234             m_container.push_back(_Val);
235         }
236
237         iterator erase(iterator _Where) {
238             removeParent(*_Where);
239             if (m_list)
240                 removeChild(*_Where);
241             else
242                 delete *_Where.m_iter;
243             return m_container.erase(_Where.m_iter);
244         }
245
246         iterator erase(iterator _First, iterator _Last) {
247             for (iterator i=_First; i!=_Last; i++) {
248                 removeParent(*i);
249                 if (m_list)
250                     removeChild(*i);
251                 else
252                     delete *i.m_iter;
253             }
254             return m_container.erase(_First,_Last);
255         }
256
257         void clear() {
258             erase(begin(),end());
259         }
260
261     private:
262         void setParent(const_reference _Val) {
263             if (_Val->getParent())
264                 throw XMLObjectException("Child object already has a parent.");
265             _Val->setParent(m_parent);
266             DOMCachingXMLObject* dc=dynamic_cast<DOMCachingXMLObject*>(_Val);
267             if (dc) {
268                 dc->releaseParentDOM(true);
269             }
270         }
271
272         void removeParent(const_reference _Val) {
273             if (_Val->getParent()!=m_parent)
274                 throw XMLObjectException("Child object not owned by this parent.");
275             _Val->setParent(NULL);
276             DOMCachingXMLObject* dc=dynamic_cast<DOMCachingXMLObject*>(m_parent);
277             if (dc) {
278                 dc->releaseParentDOM(true);
279             }
280         }
281
282         void removeChild(const_reference _Val) {
283             for (typename std::list<_Ty*>::iterator i=m_list->begin(); i!=m_list->end(); i++) {
284                 if ((*i)==_Val) {
285                     m_list->erase(i);
286                     delete _Val;
287                     return;
288                 }
289             }
290         }
291     };
292
293 };
294
295 #endif /* __xmltooling_list_h__ */