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 #ifndef _CONNECTIVITY_DBASE_INDEXNODE_HXX_
28 #define _CONNECTIVITY_DBASE_INDEXNODE_HXX_
29 
30 #include "file/fcode.hxx"
31 #include "file/FTable.hxx"
32 #include "dbase/DIndexPage.hxx"
33 #include "connectivity/FValue.hxx"
34 #include <tools/ref.hxx>
35 
36 #define NODE_NOTFOUND 0xFFFF
37 #define PAGE_SIZE 512
38 
39 namespace connectivity
40 {
41 	namespace dbase
42 	{
43 
44 		class ONDXNode;
45 		class ODbaseIndex;
46 		//==================================================================
47 		// Index Key
48 		//==================================================================
49 		typedef file::OOperand ONDXKey_BASE;
50 		class ONDXKey : public ONDXKey_BASE
51 		{
52 			friend class ONDXNode;
53 			sal_uInt32			nRecord;				/* Satzzeiger				*/
54 			ORowSetValue	xValue;					/* Schluesselwert			*/
55 
56 		public:
57 			ONDXKey(sal_uInt32 nRec=0);
58 			ONDXKey(const ORowSetValue& rVal, sal_Int32 eType, sal_uInt32 nRec);
59 			ONDXKey(const rtl::OUString& aStr, sal_uInt32 nRec = 0);
60 			ONDXKey(double aVal, sal_uInt32 nRec = 0);
61 
62 			inline ONDXKey(const ONDXKey& rKey);
63 
64 			inline ONDXKey& operator= (const ONDXKey& rKey);
65 			virtual void setValue(const ORowSetValue& _rVal);
66 
67 			virtual const ORowSetValue& getValue() const;
68 
69 			sal_uInt32 GetRecord() const		{ return nRecord;	}
70 			void setRecord(sal_uInt32 _nRec)	{ nRecord = _nRec;	}
71 			void   ResetRecord()			{ nRecord = 0;		}
72 
73 			sal_Bool operator == (const ONDXKey& rKey) const;
74 			sal_Bool operator != (const ONDXKey& rKey) const;
75 			sal_Bool operator <	 (const ONDXKey& rKey) const;
76 			sal_Bool operator <= (const ONDXKey& rKey) const;
77 			sal_Bool operator >  (const ONDXKey& rKey) const;
78 			sal_Bool operator >= (const ONDXKey& rKey) const;
79 
80 			sal_Bool Load (SvFileStream& rStream, sal_Bool bText);
81 			sal_Bool Write(SvFileStream& rStream, sal_Bool bText);
82 
83 			static sal_Bool IsText(sal_Int32 eType);
84 
85 		private:
86 			StringCompare Compare(const ONDXKey& rKey) const;
87 		};
88 
89 
90 
91 
92 		//==================================================================
93 		// Index Seitenverweis
94 		//==================================================================
95 		SV_DECL_REF(ONDXPage) // Basisklasse da weitere Informationen gehalten werden muessen
96 
97 
98 		class ONDXPagePtr : public ONDXPageRef
99 		{
100 			friend  SvStream& operator << (SvStream &rStream, const ONDXPagePtr&);
101 			friend  SvStream& operator >> (SvStream &rStream, ONDXPagePtr&);
102 
103 			sal_uInt32	nPagePos;		// Position in der Indexdatei
104 
105 		public:
106 			ONDXPagePtr(sal_uInt32 nPos = 0):nPagePos(nPos){}
107 			ONDXPagePtr(const ONDXPagePtr& rRef);
108 			ONDXPagePtr(ONDXPage* pRefPage);
109 
110 			ONDXPagePtr& operator=(const ONDXPagePtr& rRef);
111 			ONDXPagePtr& operator=(ONDXPage* pPageRef);
112 
113 			sal_uInt32 GetPagePos() const {return nPagePos;}
114 			sal_Bool HasPage() const {return nPagePos != 0;}
115 			//	sal_Bool Is() const { return isValid(); }
116 		};
117 		//==================================================================
118 		// Index Seite
119 		//==================================================================
120 		class ONDXPage : public SvRefBase
121 		{
122 			friend class ODbaseIndex;
123 
124 			friend  SvStream& operator << (SvStream &rStream, const ONDXPage&);
125 			friend  SvStream& operator >> (SvStream &rStream, ONDXPage&);
126 
127 			sal_uInt32		nPagePos;				// Position in der Indexdatei
128 			sal_Bool		bModified : 1;
129 			sal_uInt16		nCount;
130 
131 			ONDXPagePtr	aParent,			// VaterSeite
132 						aChild;				// Zeiger auf rechte ChildPage
133 			ODbaseIndex& rIndex;
134 			ONDXNode*  ppNodes;				// array von Knoten
135 
136 		public:
137 			// Knoten Operationen
138 			sal_uInt16	Count() const {return nCount;}
139 
140 			sal_Bool	Insert(ONDXNode& rNode, sal_uInt32 nRowsLeft = 0);
141 			sal_Bool	Insert(sal_uInt16 nIndex, ONDXNode& rNode);
142 			sal_Bool	Append(ONDXNode& rNode);
143 			sal_Bool	Delete(sal_uInt16);
144 			void	Remove(sal_uInt16);
145 			void	Release(sal_Bool bSave = sal_True);
146 			void	ReleaseFull(sal_Bool bSave = sal_True);
147 
148 			// Aufteilen und Zerlegen
149 			ONDXNode Split(ONDXPage& rPage);
150 			void Merge(sal_uInt16 nParentNodePos, ONDXPagePtr xPage);
151 
152 			// Zugriffsoperationen
153 			ONDXNode& operator[] (sal_uInt16 nPos);
154 			const ONDXNode& operator[] (sal_uInt16 nPos) const;
155 
156 			sal_Bool IsRoot() const;
157 			sal_Bool IsLeaf() const;
158 			sal_Bool IsModified() const;
159 			sal_Bool HasParent();
160 			sal_Bool HasChild() const;
161 
162 			sal_Bool IsFull() const;
163 
164 			sal_uInt32 GetPagePos() const {return nPagePos;}
165 			ONDXPagePtr& GetChild(ODbaseIndex* pIndex = 0);
166 
167 			// Parent braucht nicht nachgeladen zu werden
168 			ONDXPagePtr GetParent();
169 			ODbaseIndex& GetIndex() {return rIndex;}
170 			const ODbaseIndex& GetIndex() const {return rIndex;}
171 
172 			// Setzen des Childs, ueber Referenz, um die PagePos zu erhalten
173 			void SetChild(ONDXPagePtr aCh);
174 			void SetParent(ONDXPagePtr aPa);
175 
176 			sal_uInt16 Search(const ONDXKey& rSearch);
177 			sal_uInt16 Search(const ONDXPage* pPage);
178 			void   SearchAndReplace(const ONDXKey& rSearch, ONDXKey& rReplace);
179 
180 		protected:
181 			ONDXPage(ODbaseIndex& rIndex, sal_uInt32 nPos, ONDXPage* = NULL);
182 			~ONDXPage();
183 
184 			virtual void QueryDelete();
185 
186 			void SetModified(sal_Bool bMod) {bModified = bMod;}
187 			void SetPagePos(sal_uInt32 nPage) {nPagePos = nPage;}
188 
189 			sal_Bool Find(const ONDXKey&);	// rek. Abstieg
190 			sal_uInt16 FindPos(const ONDXKey& rKey) const;
191 
192 #if OSL_DEBUG_LEVEL > 1
193 			void PrintPage();
194 #endif
195 		};
196 
197 		SV_IMPL_REF(ONDXPage);
198 
199 		SvStream& operator << (SvStream &rStream, const ONDXPagePtr&);
200 		SvStream& operator >> (SvStream &rStream, ONDXPagePtr&);
201 
202 		inline sal_Bool ONDXPage::IsRoot() const {return !aParent.Is();}
203 		inline sal_Bool ONDXPage::IsLeaf() const {return !aChild.HasPage();}
204 		inline sal_Bool ONDXPage::IsModified() const {return bModified;}
205 		inline sal_Bool ONDXPage::HasParent() {return aParent.Is();}
206 		inline sal_Bool ONDXPage::HasChild() const {return aChild.HasPage();}
207 		inline ONDXPagePtr ONDXPage::GetParent() {return aParent;}
208 
209 		inline void ONDXPage::SetParent(ONDXPagePtr aPa = ONDXPagePtr())
210 		{
211 			aParent = aPa;
212 		}
213 
214 		inline void ONDXPage::SetChild(ONDXPagePtr aCh = ONDXPagePtr())
215 		{
216 			aChild = aCh;
217 			if (aChild.Is())
218 				aChild->SetParent(this);
219 		}
220 		SvStream& operator >> (SvStream &rStream, ONDXPage& rPage);
221 		SvStream& operator << (SvStream &rStream, const ONDXPage& rPage);
222 
223 
224 		typedef ::std::vector<ONDXPage*>	ONDXPageList;
225 
226 		//==================================================================
227 		// Index Knoten
228 		//==================================================================
229 		class ONDXNode
230 		{
231 			friend class ONDXPage;
232 			ONDXPagePtr aChild;				/* naechster Seitenverweis	*/
233 			ONDXKey	  aKey;
234 
235 		public:
236 			ONDXNode(){}
237 			ONDXNode(const ONDXKey& rKey,
238 					   ONDXPagePtr aPagePtr = ONDXPagePtr())
239                        :aChild(aPagePtr),aKey(rKey) {}
240 
241 			// verweist der Knoten auf eine Seite
242 			sal_Bool			HasChild() const {return aChild.HasPage();}
243 			// Ist ein Index angegeben, kann gegebenfalls die Seite nachgeladen werden
244 			ONDXPagePtr&	GetChild(ODbaseIndex* pIndex = NULL, ONDXPage* = NULL);
245 
246 			const ONDXKey& GetKey() const	{ return aKey;}
247 			ONDXKey&	   GetKey()			{ return aKey;}
248 
249 			// Setzen des Childs, ueber Referenz, um die PagePos zu erhalten
250 			void			SetChild(ONDXPagePtr aCh = ONDXPagePtr(), ONDXPage* = NULL);
251 			void			SetKey(ONDXKey& rKey) {aKey = rKey;}
252 
253 			void Write(SvStream &rStream, const ONDXPage& rPage) const;
254 			void Read(SvStream &rStream, ODbaseIndex&);
255 		};
256 		//==================================================================
257 		// inline implementation
258 		//==================================================================
259 //		inline ONDXKey::ONDXKey(const ORowSetValue& rVal, sal_Int32 eType, sal_uInt32 nRec)
260 //			: ONDXKey_BASE(eType)
261 //			, nRecord(nRec),xValue(rVal)
262 //		{
263 //		}
264 
265 
266 //		inline ONDXKey::ONDXKey(const rtl::OUString& aStr, sal_uInt32 nRec)
267 //					: ONDXKey_BASE(::com::sun::star::sdbc::DataType::VARCHAR)
268 //					 ,nRecord(nRec)
269 //		{
270 //			if (aStr.len())
271 //				xValue = aStr;
272 //		}
273 
274 //		inline ONDXKey::ONDXKey(double aVal, sal_uInt32 nRec)
275 //					 : ONDXKey_BASE(::com::sun::star::sdbc::DataType::DOUBLE)
276 //					 ,nRecord(nRec)
277 //					 ,xValue(aVal)
278 //		{
279 //		}
280 
281 //		inline ONDXKey::ONDXKey(sal_uInt32 nRec)
282 //					 :nRecord(nRec)
283 //		{
284 //		}
285 
286 		inline ONDXKey::ONDXKey(const ONDXKey& rKey)
287 					 : ONDXKey_BASE(rKey.getDBType())
288 					 ,nRecord(rKey.nRecord)
289 					 ,xValue(rKey.xValue)
290 		{
291 		}
292 
293 		inline ONDXKey& ONDXKey::operator=(const ONDXKey& rKey)
294 		{
295 			if(&rKey == this)
296 				return *this;
297 
298 			xValue = rKey.xValue;
299 			nRecord = rKey.nRecord;
300 			m_eDBType = rKey.getDBType();
301 			return *this;
302 		}
303 
304 		inline sal_Bool ONDXKey::operator == (const ONDXKey& rKey) const
305 		{
306 			if(&rKey == this)
307 				return sal_True;
308 			return Compare(rKey) == COMPARE_EQUAL;
309 		}
310 		inline sal_Bool ONDXKey::operator != (const ONDXKey& rKey) const
311 		{
312 			return !operator== (rKey);
313 		}
314 		inline sal_Bool ONDXKey::operator <  (const ONDXKey& rKey) const
315 		{
316 			return Compare(rKey) == COMPARE_LESS;
317 		}
318 		inline sal_Bool ONDXKey::operator >  (const ONDXKey& rKey) const
319 		{
320 			return Compare(rKey) == COMPARE_GREATER;
321 		}
322 		inline sal_Bool ONDXKey::operator <= (const ONDXKey& rKey) const
323 		{
324 			return !operator > (rKey);
325 		}
326 		inline sal_Bool ONDXKey::operator >= (const ONDXKey& rKey) const
327 		{
328 			return !operator< (rKey);
329 		}
330 
331 		inline void ONDXNode::SetChild(ONDXPagePtr aCh, ONDXPage* pParent)
332 		{
333 			aChild = aCh;
334 			if (aChild.Is())
335 				aChild->SetParent(pParent);
336 		}
337 
338 	}
339 
340 }
341 
342 
343 
344 
345 #endif // _CONNECTIVITY_DBASE_INDEXNODE_HXX_
346 
347 
348