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_connectivity.hxx"
30 #include "TSkipDeletedSet.hxx"
31 #include <osl/diagnose.h>
32 #include <rtl/logfile.hxx>
33 
34 using namespace connectivity;
35 // -----------------------------------------------------------------------------
36 OSkipDeletedSet::OSkipDeletedSet(IResultSetHelper* _pHelper)
37 	: m_pHelper(_pHelper)
38     ,m_bDeletedVisible(false)
39 {
40     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "commontools", "Ocke.Janssen@sun.com", "OSkipDeletedSet::OSkipDeletedSet" );
41     m_aBookmarksPositions.reserve(256);
42 }
43 // -----------------------------------------------------------------------------
44 OSkipDeletedSet::~OSkipDeletedSet()
45 {
46 	m_aBookmarksPositions.clear();
47 	//m_aBookmarks.clear();
48 }
49 // -----------------------------------------------------------------------------
50 sal_Bool OSkipDeletedSet::skipDeleted(IResultSetHelper::Movement _eCursorPosition, sal_Int32 _nOffset, sal_Bool _bRetrieveData)
51 {
52     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "commontools", "Ocke.Janssen@sun.com", "OSkipDeletedSet::skipDeleted" );
53 	OSL_ENSURE(_eCursorPosition != IResultSetHelper::BOOKMARK,"OSkipDeletedSet::SkipDeleted can't be called for BOOKMARK");
54 
55 	IResultSetHelper::Movement eDelPosition = _eCursorPosition;
56 	sal_Int32 nDelOffset = abs(_nOffset);
57 
58 	switch (_eCursorPosition)
59 	{
60 		case IResultSetHelper::ABSOLUTE:
61             return moveAbsolute(_nOffset,_bRetrieveData);
62 		case IResultSetHelper::FIRST:					// set the movement when positioning failed
63 			eDelPosition = IResultSetHelper::NEXT;
64 			nDelOffset = 1;
65 			break;
66 		case IResultSetHelper::LAST:
67 			eDelPosition = IResultSetHelper::PRIOR; // lsat row is invalid so position before
68 			nDelOffset = 1;
69 			break;
70 		case IResultSetHelper::RELATIVE:
71 			eDelPosition = (_nOffset >= 0) ? IResultSetHelper::NEXT : IResultSetHelper::PRIOR;
72 			break;
73         default:
74             break;
75 	}
76 
77 	sal_Bool bDone			= sal_True;
78 	sal_Bool bDataFound		= sal_False;
79 
80 	if (_eCursorPosition == IResultSetHelper::LAST)
81 	{
82         RTL_LOGFILE_CONTEXT_TRACE( aLogger, "OSkipDeletedSet::skipDeleted: last" );
83 		sal_Int32 nBookmark = 0;
84 		// first position on the last known row
85 		if ( m_aBookmarksPositions.empty() )
86 		{
87 			bDataFound = m_pHelper->move(IResultSetHelper::FIRST, 0, _bRetrieveData);
88 			if(bDataFound && (m_bDeletedVisible || !m_pHelper->isRowDeleted()))
89 				//m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(m_pHelper->getDriverPos(),m_aBookmarksPositions.size()+1)).first);
90                 m_aBookmarksPositions.push_back(m_pHelper->getDriverPos());
91 		}
92 		else
93 		{
94 			// I already have a bookmark so we can positioned on that and look if it is the last one
95 			nBookmark = (*m_aBookmarksPositions.rbegin())/*->first*/;
96 
97 			bDataFound = m_pHelper->move(IResultSetHelper::BOOKMARK, nBookmark, _bRetrieveData);
98 			OSL_ENSURE((m_bDeletedVisible || !m_pHelper->isRowDeleted()),"A bookmark should not be deleted!");
99 		}
100 
101 
102 		// and than move forward until we are after the last row
103 		while(bDataFound)
104 		{
105 			bDataFound = m_pHelper->move(IResultSetHelper::NEXT, 1, sal_False); // we don't need the data here
106 			if( bDataFound && ( m_bDeletedVisible || !m_pHelper->isRowDeleted()) )
107 			{	// we weren't on the last row we remember it and move on
108                 m_aBookmarksPositions.push_back(m_pHelper->getDriverPos());
109 				//m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(m_pHelper->getDriverPos(),m_aBookmarksPositions.size()+1)).first);
110 			}
111 			else if(!bDataFound && !m_aBookmarksPositions.empty() )
112 			{
113 				// i already know the last bookmark :-)
114 				// now we only have to repositioning us to the last row
115 				nBookmark = (*m_aBookmarksPositions.rbegin())/*->first*/;
116 				bDataFound = m_pHelper->move(IResultSetHelper::BOOKMARK, nBookmark, _bRetrieveData);
117 				break;
118 			}
119 		}
120 		return bDataFound;
121 	}
122 	else if (_eCursorPosition != IResultSetHelper::RELATIVE)
123 	{
124 		bDataFound = m_pHelper->move(_eCursorPosition, _nOffset, _bRetrieveData);
125 		bDone = bDataFound && (m_bDeletedVisible || !m_pHelper->isRowDeleted());
126 	}
127 	else
128 	{
129 		bDataFound = m_pHelper->move(eDelPosition, 1, _bRetrieveData);
130 		if (bDataFound && (m_bDeletedVisible || !m_pHelper->isRowDeleted()))
131 		{
132             bDone = (--nDelOffset) == 0;
133             if ( !bDone )
134                 m_aBookmarksPositions.push_back(m_pHelper->getDriverPos());
135 			//m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(m_pHelper->getDriverPos(),m_aBookmarksPositions.size()+1)).first);
136 		}
137 		else
138 			bDone = sal_False;
139 	}
140 
141     while (bDataFound && !bDone)            // solange iterieren bis man auf einem gueltigen Satz ist
142 	{
143 		bDataFound = m_pHelper->move(eDelPosition, 1, _bRetrieveData);
144 		if (_eCursorPosition != IResultSetHelper::RELATIVE)
145 			bDone = bDataFound && (m_bDeletedVisible || !m_pHelper->isRowDeleted());
146 		else if (bDataFound && (m_bDeletedVisible || !m_pHelper->isRowDeleted()))
147 		{
148             bDone = (--nDelOffset) == 0;
149             if ( !bDone )
150                 m_aBookmarksPositions.push_back(m_pHelper->getDriverPos());
151 			//m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(m_pHelper->getDriverPos(),m_aBookmarksPositions.size()+1)).first);
152 		}
153 		else
154 			bDone = sal_False;
155 	}
156 
157 	if(bDataFound && bDone)
158 	{
159         const sal_Int32 nDriverPos = m_pHelper->getDriverPos();
160         if ( m_bDeletedVisible )
161         {
162             if ( nDriverPos > (sal_Int32)m_aBookmarksPositions.size() )
163                 m_aBookmarksPositions.push_back(nDriverPos);
164         }
165         else if ( ::std::find(m_aBookmarksPositions.begin(),m_aBookmarksPositions.end(),nDriverPos) == m_aBookmarksPositions.end() )
166             m_aBookmarksPositions.push_back(nDriverPos);
167 		/*sal_Int32 nDriverPos = m_pHelper->getDriverPos();
168 		if(m_aBookmarks.find(nDriverPos) == m_aBookmarks.end())
169 			m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(nDriverPos,m_aBookmarksPositions.size()+1)).first);*/
170 	}
171 
172 	return bDataFound;
173 }
174 // -------------------------------------------------------------------------
175 sal_Bool OSkipDeletedSet::moveAbsolute(sal_Int32 _nPos,sal_Bool _bRetrieveData)
176 {
177     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "commontools", "Ocke.Janssen@sun.com", "OSkipDeletedSet::moveAbsolute" );
178 	sal_Bool bDataFound = sal_False;
179 	sal_Int32 nNewPos = _nPos;
180 	if(nNewPos > 0)
181 	{
182 		if((sal_Int32)m_aBookmarksPositions.size() < nNewPos)
183 		{
184 			// bookmark isn't known yet
185 			// start at the last known position
186 			sal_Int32 nCurPos = 0,nLastBookmark = 1;
187 			if ( m_aBookmarksPositions.empty() )
188             {
189 				bDataFound = m_pHelper->move(IResultSetHelper::FIRST, 0, _bRetrieveData );
190 				if(bDataFound && (m_bDeletedVisible || !m_pHelper->isRowDeleted()))
191 				{
192 					++nCurPos;
193                     m_aBookmarksPositions.push_back(m_pHelper->getDriverPos());
194 					//m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(m_pHelper->getDriverPos(),m_aBookmarksPositions.size()+1)).first);
195 					--nNewPos;
196 				}
197 			} // if ( m_aBookmarksPositions.empty() )
198             else
199 			{
200 				nLastBookmark	= (*m_aBookmarksPositions.rbegin())/*->first*/;
201 				nCurPos			= /*(**/m_aBookmarksPositions.size()/*->second*/;
202 				nNewPos		    = nNewPos - nCurPos;
203 				bDataFound		= m_pHelper->move(IResultSetHelper::BOOKMARK, nLastBookmark, _bRetrieveData);
204 			}
205 
206 			// now move to that row we need and don't count deleted rows
207 			while (bDataFound && nNewPos)
208 			{
209 				bDataFound = m_pHelper->move(IResultSetHelper::NEXT, 1, _bRetrieveData);
210 				if(bDataFound && (m_bDeletedVisible || !m_pHelper->isRowDeleted()))
211 				{
212 					++nCurPos;
213                     m_aBookmarksPositions.push_back(m_pHelper->getDriverPos());
214 					//m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(m_pHelper->getDriverPos(),m_aBookmarksPositions.size()+1)).first);
215 					--nNewPos;
216 				}
217 			}
218 		}
219 		else
220 		{
221 			const sal_Int32 nBookmark = m_aBookmarksPositions[nNewPos-1]/*->first*/;
222 			bDataFound = m_pHelper->move(IResultSetHelper::BOOKMARK,nBookmark, _bRetrieveData);
223 			OSL_ENSURE((m_bDeletedVisible || !m_pHelper->isRowDeleted()),"moveAbsolute: row can't be deleted!");
224 		}
225 	}
226 	else
227 	{
228 		++nNewPos;
229 		bDataFound = skipDeleted(IResultSetHelper::LAST,0,nNewPos == 0);
230 
231 		for(sal_Int32 i=nNewPos+1;bDataFound && i <= 0;++i)
232 			bDataFound = skipDeleted(IResultSetHelper::PRIOR,1,i == 0);
233 
234 	}
235 	return bDataFound;
236 }
237 // -----------------------------------------------------------------------------
238 void OSkipDeletedSet::clear()
239 {
240     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "commontools", "Ocke.Janssen@sun.com", "OSkipDeletedSet::clear" );
241 	::std::vector<sal_Int32>().swap(m_aBookmarksPositions);
242 	//TInt2IntMap().swap(m_aBookmarks);
243 }
244 // -----------------------------------------------------------------------------
245 sal_Int32 OSkipDeletedSet::getMappedPosition(sal_Int32 _nPos) const
246 {
247     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "commontools", "Ocke.Janssen@sun.com", "OSkipDeletedSet::getMappedPosition" );
248     ::std::vector<sal_Int32>::const_iterator aFind = ::std::find(m_aBookmarksPositions.begin(),m_aBookmarksPositions.end(),_nPos);
249     if ( aFind !=  m_aBookmarksPositions.end() )
250         return (aFind - m_aBookmarksPositions.begin()) + 1;
251 	/*TInt2IntMap::const_iterator aFind = m_aBookmarks.find(_nPos);
252 	OSL_ENSURE(aFind != m_aBookmarks.end(),"OSkipDeletedSet::getMappedPosition() invalid bookmark!");
253 	return aFind->second;*/
254     OSL_ENSURE(0,"Why!");
255     return -1;
256 }
257 // -----------------------------------------------------------------------------
258 void OSkipDeletedSet::insertNewPosition(sal_Int32 _nPos)
259 {
260     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "commontools", "Ocke.Janssen@sun.com", "OSkipDeletedSet::insertNewPosition" );
261 	//OSL_ENSURE(m_aBookmarks.find(_nPos) == m_aBookmarks.end(),"OSkipDeletedSet::insertNewPosition: Invalid position");
262 	//m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(_nPos,m_aBookmarksPositions.size()+1)).first);
263     //OSL_ENSURE(::std::find(m_aBookmarksPositions.begin(),m_aBookmarksPositions.end(),_nPos) == m_aBookmarksPositions.end(),"Invalid driver pos");
264     m_aBookmarksPositions.push_back(_nPos);
265 }
266 // -----------------------------------------------------------------------------
267 void OSkipDeletedSet::deletePosition(sal_Int32 _nBookmark)
268 {
269     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "commontools", "Ocke.Janssen@sun.com", "OSkipDeletedSet::deletePosition" );
270     ::std::vector<sal_Int32>::iterator aFind = ::std::find(m_aBookmarksPositions.begin(),m_aBookmarksPositions.end(),_nBookmark);
271     if ( aFind !=  m_aBookmarksPositions.end() )
272     {
273 	//TInt2IntMap::iterator aFind = m_aBookmarks.find(_nPos);
274 	//OSL_ENSURE(aFind != m_aBookmarks.end(),"OSkipDeletedSet::deletePosition() bookmark not found!");
275 	//TInt2IntMap::iterator aIter = aFind;
276         m_aBookmarksPositions.erase(aFind);
277 	    //for (; aFind != m_aBookmarksPositions.end() ; ++aIter)
278 		   // --(aFind->second);
279     } // if ( aFind !=  m_aBookmarksPositions.end() )
280 	//m_aBookmarksPositions.erase(m_aBookmarksPositions.begin() + aFind->second-1);
281 	//m_aBookmarks.erase(_nPos);
282 }
283 // -----------------------------------------------------------------------------
284