xref: /trunk/main/comphelper/source/container/container.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
30 #include <com/sun/star/uno/XInterface.hpp>
31 #include <com/sun/star/container/XIndexAccess.hpp>
32 #include <com/sun/star/container/XChild.hpp>
33 #include <comphelper/container.hxx>
34 #include <osl/diagnose.h>
35 
36 //.........................................................................
37 namespace comphelper
38 {
39 //.........................................................................
40 
41 //==============================================================================
42 IndexAccessIterator::IndexAccessIterator(::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> xStartingPoint)
43     :m_xStartingPoint(xStartingPoint)
44     ,m_xCurrentObject(NULL)
45 {
46     OSL_ENSURE(m_xStartingPoint.is(), "IndexAccessIterator::IndexAccessIterator : no starting point !");
47 }
48 
49 IndexAccessIterator::~IndexAccessIterator() {}
50 
51 //------------------------------------------------------------------------------
52 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> IndexAccessIterator::Next()
53 {
54     sal_Bool bCheckingStartingPoint = !m_xCurrentObject.is();
55         // ist die aktuelle Node der Anfangspunkt ?
56     sal_Bool bAlreadyCheckedCurrent = m_xCurrentObject.is();
57         // habe ich die aktuelle Node schon mal mittels ShouldHandleElement testen ?
58     if (!m_xCurrentObject.is())
59         m_xCurrentObject = m_xStartingPoint;
60 
61     ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> xSearchLoop( m_xCurrentObject);
62     sal_Bool bHasMoreToSearch = sal_True;
63     sal_Bool bFoundSomething = sal_False;
64     while (!bFoundSomething && bHasMoreToSearch)
65     {
66         // pre-order-traversierung
67         if (!bAlreadyCheckedCurrent && ShouldHandleElement(xSearchLoop))
68         {
69             m_xCurrentObject = xSearchLoop;
70             bFoundSomething = sal_True;
71         }
72         else
73         {
74             // zuerst absteigen, wenn moeglich
75             ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess> xContainerAccess(xSearchLoop, ::com::sun::star::uno::UNO_QUERY);
76             if (xContainerAccess.is() && xContainerAccess->getCount() && ShouldStepInto(xContainerAccess))
77             {   // zum ersten Child
78                 ::com::sun::star::uno::Any aElement(xContainerAccess->getByIndex(0));
79                 xSearchLoop = *(::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>*)aElement.getValue();
80                 bCheckingStartingPoint = sal_False;
81 
82                 m_arrChildIndizies.push_back((sal_Int32)0);
83             }
84             else
85             {
86                 // dann nach oben und nach rechts, wenn moeglich
87                 while (m_arrChildIndizies.size() > 0)
88                 {   // (mein Stack ist nich leer, also kann ich noch nach oben gehen)
89                     ::com::sun::star::uno::Reference< ::com::sun::star::container::XChild> xChild(xSearchLoop, ::com::sun::star::uno::UNO_QUERY);
90                     OSL_ENSURE(xChild.is(), "IndexAccessIterator::Next : a content has no approriate interface !");
91 
92                     ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> xParent( xChild->getParent());
93                     xContainerAccess = ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess>(xParent, ::com::sun::star::uno::UNO_QUERY);
94                     OSL_ENSURE(xContainerAccess.is(), "IndexAccessIterator::Next : a content has an invalid parent !");
95 
96                     // den Index, den SearchLoop in diesem Parent hatte, von meinem 'Stack'
97                     sal_Int32 nOldSearchChildIndex = m_arrChildIndizies[m_arrChildIndizies.size() - 1];
98                     m_arrChildIndizies.pop_back();
99 
100                     if (nOldSearchChildIndex < xContainerAccess->getCount() - 1)
101                     {   // auf dieser Ebene geht es noch nach rechts
102                         ++nOldSearchChildIndex;
103                         // also das naechste Child
104                         ::com::sun::star::uno::Any aElement(xContainerAccess->getByIndex(nOldSearchChildIndex));
105                         xSearchLoop = *(::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>*) aElement.getValue();
106                         bCheckingStartingPoint = sal_False;
107                         // und dessen Position auf den 'Stack'
108                         m_arrChildIndizies.push_back((sal_Int32)nOldSearchChildIndex);
109 
110                         break;
111                     }
112                     // hierher komme ich, wenn es auf der aktuellen Ebene nicht nach rechts geht, dann mache ich eine darueber weiter
113                     xSearchLoop = xParent;
114                     bCheckingStartingPoint = sal_False;
115                 }
116 
117                 if ((m_arrChildIndizies.size() == 0) && !bCheckingStartingPoint)
118                 {   // das ist genau dann der Fall, wenn ich keinen rechten Nachbarn fuer irgendeinen der direkten Vorfahren des
119                     // urspruenglichen xSearchLoop gefunden habe
120                     bHasMoreToSearch = sal_False;
121                 }
122             }
123 
124             if (bHasMoreToSearch)
125             {   // ich habe in xSearchLoop jetzt ein Interface eines 'Knotens' meines 'Baumes', den ich noch abtesten kann
126                 if (ShouldHandleElement(xSearchLoop))
127                 {
128                     m_xCurrentObject = xSearchLoop;
129                     bFoundSomething = sal_True;
130                 }
131                 else
132                     if (bCheckingStartingPoint)
133                         // ich bin noch am Anfang, konnte nicht absteigen, und habe an diesem Anfang nix gefunden -> nix mehr zu tun
134                         bHasMoreToSearch = sal_False;
135                 bAlreadyCheckedCurrent = sal_True;
136             }
137         }
138     }
139 
140     if (!bFoundSomething)
141     {
142         OSL_ENSURE(m_arrChildIndizies.size() == 0, "IndexAccessIterator::Next : items left on stack ! how this ?");
143         Invalidate();
144     }
145 
146     return m_xCurrentObject;
147 }
148 
149 //.........................................................................
150 }   // namespace comphelper
151 //.........................................................................
152 
153 
154