/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"
#include "dbase/dindexnode.hxx"
#include "connectivity/CommonTools.hxx"
#include <osl/thread.h>
#include "dbase/DIndex.hxx"
#include <tools/debug.hxx>
#include "diagnose_ex.h"

#include <algorithm>


using namespace connectivity;
using namespace connectivity::dbase;
using namespace connectivity::file;
using namespace com::sun::star::sdbc;
// -----------------------------------------------------------------------------
ONDXKey::ONDXKey(sal_uInt32 nRec)
	:nRecord(nRec)
{
}
// -----------------------------------------------------------------------------
ONDXKey::ONDXKey(const ORowSetValue& rVal, sal_Int32 eType, sal_uInt32 nRec)
	: ONDXKey_BASE(eType)
	, nRecord(nRec)
	, xValue(rVal)
{
}
// -----------------------------------------------------------------------------
ONDXKey::ONDXKey(const rtl::OUString& aStr, sal_uInt32 nRec)
	: ONDXKey_BASE(::com::sun::star::sdbc::DataType::VARCHAR)
	 ,nRecord(nRec)
{
	if (aStr.getLength())
	{
		xValue = aStr;
		xValue.setBound(sal_True);
	}
}
// -----------------------------------------------------------------------------

ONDXKey::ONDXKey(double aVal, sal_uInt32 nRec)
	: ONDXKey_BASE(::com::sun::star::sdbc::DataType::DOUBLE)
	 ,nRecord(nRec)
	 ,xValue(aVal)
{
}
// -----------------------------------------------------------------------------

//==================================================================
// Index Seite
//==================================================================
ONDXPage::ONDXPage(ODbaseIndex& rInd, sal_uInt32 nPos, ONDXPage* pParent)
		   :nPagePos(nPos)
           ,bModified(sal_False)
           ,nCount(0)
           ,aParent(pParent)
           ,rIndex(rInd)
		   ,ppNodes(NULL)
{
	sal_uInt16 nT = rIndex.getHeader().db_maxkeys;
	ppNodes = new ONDXNode[nT];
}

//------------------------------------------------------------------
ONDXPage::~ONDXPage()
{
	delete[] ppNodes;
	//	delete aParent;
	//	delete aChild;
}
//------------------------------------------------------------------
void ONDXPage::QueryDelete()
{
	// Ablegen im GarbageCollector
	if (IsModified() && rIndex.m_pFileStream)
		(*rIndex.m_pFileStream) << *this;

	bModified = sal_False;
	if (rIndex.UseCollector())
	{
		if (aChild.Is())
			aChild->Release(sal_False);

		for (sal_uInt16 i = 0; i < rIndex.getHeader().db_maxkeys;i++)
		{
			if (ppNodes[i].GetChild().Is())
				ppNodes[i].GetChild()->Release(sal_False);

			ppNodes[i] = ONDXNode();
		}
		RestoreNoDelete();

		nCount = 0;
		aParent.Clear();
		rIndex.Collect(this);
	}
	else
		SvRefBase::QueryDelete();
}
//------------------------------------------------------------------
ONDXPagePtr& ONDXPage::GetChild(ODbaseIndex* pIndex)
{
	if (!aChild.Is() && pIndex)
	{
		aChild = rIndex.CreatePage(aChild.GetPagePos(),this,aChild.HasPage());
	}
	return aChild;
}

//------------------------------------------------------------------
sal_uInt16 ONDXPage::FindPos(const ONDXKey& rKey) const
{
	// sucht nach Platz fuer den vorgegeben key auf einer Seite
	sal_uInt16 i = 0;
	while (i < nCount && rKey > ((*this)[i]).GetKey())
		   i++;

	return i;
}

//------------------------------------------------------------------
sal_Bool ONDXPage::Find(const ONDXKey& rKey)
{
	// sucht den vorgegeben key
	// Besonderheit: gelangt der Algorithmus ans Ende
	// wird immer die aktuelle Seite und die Knotenposition vermerkt
	// auf die die Bedingung <= zutrifft
	// dieses findet beim Insert besondere Beachtung
	sal_uInt16 i = 0;
	while (i < nCount && rKey > ((*this)[i]).GetKey())
		   i++;

	sal_Bool bResult = sal_False;

	if (!IsLeaf())
	{
		// weiter absteigen
		ONDXPagePtr aPage = (i==0) ? GetChild(&rIndex) : ((*this)[i-1]).GetChild(&rIndex, this);
		bResult = aPage.Is() && aPage->Find(rKey);
	}
	else if (i == nCount)
	{
		rIndex.m_aCurLeaf = this;
		rIndex.m_nCurNode = i - 1;
		bResult = sal_False;
	}
	else
	{
		bResult = rKey == ((*this)[i]).GetKey();
		rIndex.m_aCurLeaf = this;
		rIndex.m_nCurNode = bResult ? i : i - 1;
	}
	return bResult;
}

//------------------------------------------------------------------
sal_Bool ONDXPage::Insert(ONDXNode& rNode, sal_uInt32 nRowsLeft)
{
	// beim Erzeugen eines Index koennen auch mehrere Knoten eingefuegt werden
	// diese sin dann aufsteigend sortiert
	sal_Bool bAppend = nRowsLeft > 0;
	if (IsFull())
	{
		sal_Bool bResult = sal_True;
		ONDXNode aSplitNode;
		if (bAppend)
			aSplitNode = rNode;
		else
		{
			// merken des letzten Knotens
			aSplitNode = (*this)[nCount-1];
			if(rNode.GetKey() <= aSplitNode.GetKey())
			{

				// und damit habe ich im folgenden praktisch eine Node weniger
				if (IsLeaf() && this == &rIndex.m_aCurLeaf)
				{
					// geht davon aus, dass der Knoten, auf dem die Bedingung (<=)
					// zutrifft, als m_nCurNode gesetzt ist
					--nCount;	// (sonst bekomme ich u.U. Assertions und GPFs - 60593)
					bResult = Insert(rIndex.m_nCurNode + 1, rNode);
				}
				else  // Position unbekannt
				{
					sal_uInt16 nPos = NODE_NOTFOUND;
					while (++nPos < nCount && rNode.GetKey() > ((*this)[nPos]).GetKey()) ;

					--nCount;	// (sonst bekomme ich u.U. Assertions und GPFs - 60593)
					bResult = Insert(nPos, rNode);
				}

				// konnte der neue Knoten eingefuegt werden
				if (!bResult)
				{
					nCount++;
					aSplitNode = rNode;
				}
			}
			else
				aSplitNode = rNode;
		}

		sal_uInt32 nNewPagePos = rIndex.GetPageCount();
		sal_uInt32 nNewPageCount = nNewPagePos + 1;

		// Herausgeloesten Knoten beim Vater einfuegen
		if (!HasParent())
		{
			// Kein Vater, dann neue Wurzel
			ONDXPagePtr aNewRoot = rIndex.CreatePage(nNewPagePos + 1);
			aNewRoot->SetChild(this);

			rIndex.m_aRoot = aNewRoot;
			rIndex.SetRootPos(nNewPagePos + 1);
			rIndex.SetPageCount(++nNewPageCount);
		}

		// neues blatt erzeugen und Seite aufteilen
		ONDXPagePtr aNewPage = rIndex.CreatePage(nNewPagePos,aParent);
		rIndex.SetPageCount(nNewPageCount);

		// wieviele Knoten weren noch eingefuegt
		// kommen noch ausreichend, dann koennen die Seiten bis zum Rand vollgestopft werden

		ONDXNode aInnerNode;
		if (!IsLeaf() || nRowsLeft < (sal_uInt32)(rIndex.GetMaxNodes() / 2))
			aInnerNode = Split(*aNewPage);
		else
		{
			aInnerNode = (*this)[nCount - 1];
			//aInnerNode = aSplitNode;

			// Knoten zeigt auf neue Seite
			aInnerNode.SetChild(aNewPage);

			// innere Knoten haben keine Recordnummer
			if (rIndex.isUnique())
				aInnerNode.GetKey().ResetRecord();

            // neue Seite zeigt nun auf Seite des herausgeloesten Knoten
			if (!IsLeaf())
				aNewPage->SetChild(aInnerNode.GetChild());
		}

		aNewPage->Append(aSplitNode);
		ONDXPagePtr aTempParent = aParent;
		if (IsLeaf())
		{
			rIndex.m_aCurLeaf = aNewPage;
			rIndex.m_nCurNode = rIndex.m_aCurLeaf->Count() - 1;

			// Freigeben nicht benoetigter Seiten, danach besteht keine Referenz
			// mehr auf die Seite, danach kann 'this' nicht mehr gueltig sein!!!
			ReleaseFull();
		}

		// Einfuegen des herausgeloesten Knotens
		return aTempParent->Insert(aInnerNode);
	}
	else // Seite einfach weiter auffuellen
	{
		if (bAppend)
		{
			if (IsLeaf())
				rIndex.m_nCurNode = nCount - 1;
			return Append(rNode);
		}
		else
		{
			sal_uInt16 nNodePos = FindPos(rNode.GetKey());
			if (IsLeaf())
				rIndex.m_nCurNode = nNodePos;

			return Insert(nNodePos, rNode);
		}
	}
}

//------------------------------------------------------------------
sal_Bool ONDXPage::Insert(sal_uInt16 nPos, ONDXNode& rNode)
{
	sal_uInt16 nMaxCount = rIndex.getHeader().db_maxkeys;
	if (nPos >= nMaxCount)
		return sal_False;

	if (nCount)
	{
		++nCount;
		// nach rechts verschieben
		for (sal_uInt16 i = std::min((sal_uInt16)(nMaxCount-1), (sal_uInt16)(nCount-1)); nPos < i; --i)
			(*this)[i] = (*this)[i-1];
	}
	else
		if (nCount < nMaxCount)
			nCount++;

	// einfuegen an der Position
	ONDXNode& rInsertNode = (*this)[nPos];
	rInsertNode = rNode;
	if (rInsertNode.GetChild().Is())
	{
		rInsertNode.GetChild()->SetParent(this);
		rNode.GetChild()->SetParent(this);
	}

	bModified = sal_True;

	return sal_True;
}

//------------------------------------------------------------------
sal_Bool ONDXPage::Append(ONDXNode& rNode)
{
	DBG_ASSERT(!IsFull(), "kein Append moeglich");
	return Insert(nCount, rNode);
}
//------------------------------------------------------------------
void ONDXPage::Release(sal_Bool bSave)
{
	// freigeben der Pages
	if (aChild.Is())
		aChild->Release(bSave);

	// Pointer freigeben
	aChild.Clear();

	for (sal_uInt16 i = 0; i < rIndex.getHeader().db_maxkeys;i++)
	{
		if (ppNodes[i].GetChild())
			ppNodes[i].GetChild()->Release(bSave);

		ppNodes[i].GetChild().Clear();
	}
	aParent = NULL;
}
//------------------------------------------------------------------
void ONDXPage::ReleaseFull(sal_Bool bSave)
{
	ONDXPagePtr aTempParent = aParent;
	Release(bSave);

	if (aTempParent.Is())
	{
		// Freigeben nicht benoetigter Seiten, danach besteht keine Referenz
		// mehr auf die Seite, danach kann 'this' nicht mehr gueltig sein!!!
		sal_uInt16 nParentPos = aTempParent->Search(this);
		if (nParentPos != NODE_NOTFOUND)
			(*aTempParent)[nParentPos].GetChild().Clear();
		else
			aTempParent->GetChild().Clear();
	}
}
//------------------------------------------------------------------
sal_Bool ONDXPage::Delete(sal_uInt16 nNodePos)
{
	if (IsLeaf())
	{
		// Letztes Element wird geloescht
		if (nNodePos == (nCount - 1))
		{
			ONDXNode aNode = (*this)[nNodePos];

			// beim Parent muss nun der KeyValue ausgetauscht werden
			if (HasParent())
				aParent->SearchAndReplace(aNode.GetKey(),
										  (*this)[nNodePos-1].GetKey());
		}
	}

	// Loeschen des Knoten
	Remove(nNodePos);

	// Unterlauf
	if (HasParent() && nCount < (rIndex.GetMaxNodes() / 2))
	{
		// Feststellen, welcher Knoten auf die Seite zeigt
		sal_uInt16 nParentNodePos = aParent->Search(this);
		// letzte Element auf Vaterseite
		// -> zusammenlegen mit vorletzter Seite
		if (nParentNodePos == (aParent->Count() - 1))
		{
			if (!nParentNodePos)
			// zusammenlegen mit linken nachbarn
				Merge(nParentNodePos,aParent->GetChild(&rIndex));
			else
				Merge(nParentNodePos,(*aParent)[nParentNodePos-1].GetChild(&rIndex,aParent));
		}
		// sonst Seite mit naechster Seite zusammenlegen
		else
		{
			// zusammenlegen mit rechten nachbarn
			Merge(nParentNodePos + 1,((*aParent)[nParentNodePos + 1].GetChild(&rIndex,aParent)));
			nParentNodePos++;
		}
		if (HasParent() && !(*aParent)[nParentNodePos].HasChild())
			aParent->Delete(nParentNodePos);
/*
		// letzte Element auf Vaterseite
		// -> zusammenlegen mit vorletzter Seite
		if (nParentNodePos == (aParent->Count() - 1))
		{
			if (!nParentNodePos)
			// zusammenlegen mit linken nachbarn
				Merge(nParentNodePos,aParent->GetChild(&rIndex));
			else
				Merge(nParentNodePos,(*aParent)[nParentNodePos-1].GetChild(&rIndex,aParent));
		}
		// sonst Seite mit naechster Seite zusammenlegen
		else if(nParentNodePos != NODE_NOTFOUND)
		{
			// zusammenlegen mit rechten nachbarn
			Merge(nParentNodePos + 1,((*aParent)[nParentNodePos + 1].GetChild(&rIndex,aParent)));
			nParentNodePos++;
		}
		else // Sonderbehandlung
		{
            // Page ist aChild Page vom Parent => erste Page aus ppNodes an aChild anhaengen
			Merge(0,(*aParent)[0].GetChild(&rIndex,aParent));
			nParentNodePos = 0;
		}

		if (HasParent() && !(*aParent)[nParentNodePos].HasChild())
			aParent->Delete(nParentNodePos);
*/

	}
	else if (IsRoot())
		// Sicherstellen das die Position der Wurzel festgehalten wird
		rIndex.SetRootPos(nPagePos);
	return sal_True;
}


//------------------------------------------------------------------
ONDXNode ONDXPage::Split(ONDXPage& rPage)
{
	DBG_ASSERT(IsFull(), "Falsches Splitting");
	/*	Aufteilen einer Seite auf zwei
		Blatt:
			Seite 1 behaelt (n - (n/2))
			Seite 2 erhaelt (n/2)
			Knoten n/2 wird dupliziert
		Innerer Knoten:
			Seite 1 behaelt (n+1)/2
			Seite 2 erhaelt (n/2-1)
			Knoten ((n+1)/2 + 1) : wird herausgenommen
	*/
	ONDXNode aResultNode;
	if (IsLeaf())
	{
		for (sal_uInt16 i = (nCount - (nCount / 2)), j = 0 ; i < nCount; i++)
			rPage.Insert(j++,(*this)[i]);

		// dieser Knoten enthaelt einen Schluessel der noch einmal im Tree vorkommt
		// und ersetzt werden muss
		ONDXNode aLastNode = (*this)[nCount - 1];
		nCount = nCount - (nCount / 2);
		aResultNode = (*this)[nCount - 1];

		if (HasParent())
			aParent->SearchAndReplace(aLastNode.GetKey(),
									  aResultNode.GetKey());
	}
	else
	{
		for (sal_uInt16 i = (nCount + 1) / 2 + 1, j = 0 ; i < nCount; i++)
			rPage.Insert(j++,(*this)[i]);

		aResultNode = (*this)[(nCount + 1) / 2];
		nCount = (nCount + 1) / 2;

        // neue Seite zeigt nun auf Seite des herausgeloesten Knoten
		rPage.SetChild(aResultNode.GetChild());
	}
	// Knoten zeigt auf neue Seite
	aResultNode.SetChild(&rPage);

	// innere Knoten haben keine Recordnummer
	if (rIndex.isUnique())
		aResultNode.GetKey().ResetRecord();
	bModified = sal_True;
	return aResultNode;
}

//------------------------------------------------------------------
void ONDXPage::Merge(sal_uInt16 nParentNodePos, ONDXPagePtr xPage)
{
	DBG_ASSERT(HasParent(), "kein Vater vorhanden");
	DBG_ASSERT(nParentNodePos != NODE_NOTFOUND, "Falscher Indexaufbau");

	/*	Zusammenlegen zweier Seiten	*/
	ONDXNode aResultNode;
	sal_uInt16 nMaxNodes = rIndex.GetMaxNodes(),
		   nMaxNodes_2 = nMaxNodes / 2;

	// Feststellen ob Seite rechter oder linker Nachbar
	sal_Bool	bRight    = ((*xPage)[0].GetKey() > (*this)[0].GetKey()); // sal_True, wenn xPage die rechte Seite ist
	sal_uInt16	nNewCount = (*xPage).Count() + Count();

	if (IsLeaf())
	{
		// Bedingung fuers zusammenlegen
		if (nNewCount < (nMaxNodes_2 * 2))
		{
			sal_uInt16 nLastNode = bRight ? Count() - 1 : xPage->Count() - 1;
			if (bRight)
			{
                DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
                // alle Knoten aus xPage auf den linken Knoten verschieben (anhaengen)
				while (xPage->Count())
				{
					Append((*xPage)[0]);
					xPage->Remove(0);
				}
			}
			else
			{
                DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
				// xPage ist die linke Page und THIS die rechte
				while (xPage->Count())
				{
					Insert(0,(*xPage)[xPage->Count()-1]);
					xPage->Remove(xPage->Count()-1);
				}
				// alte Position von xPage beim Parent mit this ersetzen
				if (nParentNodePos)
					(*aParent)[nParentNodePos-1].SetChild(this,aParent);
				else // oder als rechten Knoten setzen
					aParent->SetChild(this);
				aParent->SetModified(sal_True);

			}

			// Child beziehung beim Vaterknoten aufheben
			(*aParent)[nParentNodePos].SetChild();
			// Austauschen des KnotenWertes, nur wenn geaenderte Page
			// die linke ist, ansonsten werde

			if(aParent->IsRoot() && aParent->Count() == 1)
			{
				(*aParent)[0].SetChild();
				aParent->ReleaseFull();
				aParent = NULL;
				rIndex.SetRootPos(nPagePos);
				rIndex.m_aRoot = this;
				SetModified(sal_True);
			}
			else
				aParent->SearchAndReplace((*this)[nLastNode].GetKey(),(*this)[nCount-1].GetKey());

			xPage->SetModified(sal_False);
			xPage->ReleaseFull(); // wird nicht mehr benoetigt
		}
		// Ausgleichen der Elemente	  nNewCount >= (nMaxNodes_2 * 2)
		else
		{
			if (bRight)
			{
                // alle Knoten aus xPage auf den linken Knoten verschieben (anhaengen)
				ONDXNode aReplaceNode = (*this)[nCount - 1];
				while (nCount < nMaxNodes_2)
				{
					Append((*xPage)[0]);
					xPage->Remove(0);
				}
				// Austauschen des KnotenWertes: Setzt alten letzten Wert durch den letzten von xPage
				aParent->SearchAndReplace(aReplaceNode.GetKey(),(*this)[nCount-1].GetKey());
			}
			else
			{
                // alle Knoten aus this vor die xPage Knoten einfuegen
				ONDXNode aReplaceNode = (*this)[nCount - 1];
				while (xPage->Count() < nMaxNodes_2)
				{
					xPage->Insert(0,(*this)[nCount-1]);
					Remove(nCount-1);
				}
				// Austauschen des KnotenWertes
				aParent->SearchAndReplace(aReplaceNode.GetKey(),(*this)[Count()-1].GetKey());
			}
		}
	}
	else // !IsLeaf()
	{
		// Bedingung fuers zusammenlegen
		if (nNewCount < nMaxNodes_2 * 2)
		{
			if (bRight)
			{
                DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
				// Vaterknoten wird mit integriert
				// erhaelt zunaechst Child von xPage
				(*aParent)[nParentNodePos].SetChild(xPage->GetChild(),aParent);
				Append((*aParent)[nParentNodePos]);
				for (sal_uInt16 i = 0 ; i < xPage->Count(); i++)
					Append((*xPage)[i]);
			}
			else
			{
                DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
				// Vaterknoten wird mit integriert
				// erhaelt zunaechst Child
				(*aParent)[nParentNodePos].SetChild(GetChild(),aParent); // Parent merkt sich mein Child
                Insert(0,(*aParent)[nParentNodePos]); // Node vom Parent bei mir einfuegen
				while (xPage->Count())
				{
					Insert(0,(*xPage)[xPage->Count()-1]);
					xPage->Remove(xPage->Count()-1);
				}
				SetChild(xPage->GetChild());

				if (nParentNodePos)
					(*aParent)[nParentNodePos-1].SetChild(this,aParent);
				else
					aParent->SetChild(this);
			}

			// danach wird der Vaterknoten zurueckgesetzt
			(*aParent)[nParentNodePos].SetChild();
			aParent->SetModified(sal_True);

			if(aParent->IsRoot() && aParent->Count() == 1)
			{
				(*aParent).SetChild();
				aParent->ReleaseFull();
				aParent = NULL;
				rIndex.SetRootPos(nPagePos);
				rIndex.m_aRoot = this;
				SetModified(sal_True);
			}
			else if(nParentNodePos)
				// Austauschen des KnotenWertes
				// beim Append wird der Bereich erweitert, beim INsert verweist der alte Knoten von xPage auf this
                // deshalb muss der Knoten auch hier aktualisiert werden
				aParent->SearchAndReplace((*aParent)[nParentNodePos-1].GetKey(),(*aParent)[nParentNodePos].GetKey());

			xPage->SetModified(sal_False);
			xPage->ReleaseFull();
		}
		// Ausgleichen der Elemente
		else
		{
			if (bRight)
			{
				while (nCount < nMaxNodes_2)
				{
					(*aParent)[nParentNodePos].SetChild(xPage->GetChild(),aParent);
					Append((*aParent)[nParentNodePos]);
					(*aParent)[nParentNodePos] = (*xPage)[0];
					xPage->Remove(0);
				}
				xPage->SetChild((*aParent)[nParentNodePos].GetChild());
				(*aParent)[nParentNodePos].SetChild(xPage,aParent);
			}
			else
			{
				while (nCount < nMaxNodes_2)
				{
					(*aParent)[nParentNodePos].SetChild(GetChild(),aParent);
					Insert(0,(*aParent)[nParentNodePos]);
					(*aParent)[nParentNodePos] = (*xPage)[xPage->Count()-1];
					xPage->Remove(xPage->Count()-1);
				}
				SetChild((*aParent)[nParentNodePos].GetChild());
				(*aParent)[nParentNodePos].SetChild(this,aParent);

			}
			aParent->SetModified(sal_True);
		}
	}
}
//==================================================================
// ONDXNode
//==================================================================

//------------------------------------------------------------------
void ONDXNode::Read(SvStream &rStream, ODbaseIndex& rIndex)
{
	rStream >> aKey.nRecord; // schluessel

	if (rIndex.getHeader().db_keytype)
	{
		double aDbl;
		rStream >> aDbl;
		aKey = ONDXKey(aDbl,aKey.nRecord);
	}
	else
	{
		ByteString aBuf;
		sal_uInt16 nLen = rIndex.getHeader().db_keylen;
		char* pStr = aBuf.AllocBuffer(nLen+1);

		rStream.Read(pStr,nLen);
		pStr[nLen] = 0;
		aBuf.ReleaseBufferAccess();
		aBuf.EraseTrailingChars();

		//	aKey = ONDXKey((aBuf,rIndex.GetDBFConnection()->GetCharacterSet()) ,aKey.nRecord);
		aKey = ONDXKey(::rtl::OUString(aBuf.GetBuffer(),aBuf.Len(),rIndex.m_pTable->getConnection()->getTextEncoding()) ,aKey.nRecord);
	}
	rStream >> aChild;
}

union NodeData
{
	double aDbl;
	char   aData[128];
} aNodeData;
//------------------------------------------------------------------
void ONDXNode::Write(SvStream &rStream, const ONDXPage& rPage) const
{
	const ODbaseIndex& rIndex = rPage.GetIndex();
	if (!rIndex.isUnique() || rPage.IsLeaf())
		rStream << (sal_uInt32)aKey.nRecord; // schluessel
	else
		rStream << (sal_uInt32)0;	// schluessel

	if (rIndex.getHeader().db_keytype) // double
	{
		if (aKey.getValue().isNull())
		{
			memset(aNodeData.aData,0,rIndex.getHeader().db_keylen);
			rStream.Write((sal_uInt8*)aNodeData.aData,rIndex.getHeader().db_keylen);
		}
		else
			rStream << (double) aKey.getValue();
	}
	else
	{
		memset(aNodeData.aData,0x20,rIndex.getHeader().db_keylen);
		if (!aKey.getValue().isNull())
		{
			::rtl::OUString sValue = aKey.getValue();
			ByteString aText(sValue.getStr(), rIndex.m_pTable->getConnection()->getTextEncoding());
			strncpy(aNodeData.aData,aText.GetBuffer(),std::min(rIndex.getHeader().db_keylen, aText.Len()));
		}
		rStream.Write((sal_uInt8*)aNodeData.aData,rIndex.getHeader().db_keylen);
	}
	rStream << aChild;
}


//------------------------------------------------------------------
ONDXPagePtr& ONDXNode::GetChild(ODbaseIndex* pIndex, ONDXPage* pParent)
{
	if (!aChild.Is() && pIndex)
	{
		aChild = pIndex->CreatePage(aChild.GetPagePos(),pParent,aChild.HasPage());
	}
	return aChild;
}

//==================================================================
// ONDXKey
//==================================================================
//------------------------------------------------------------------
sal_Bool ONDXKey::IsText(sal_Int32 eType)
{
	return eType == DataType::VARCHAR || eType == DataType::CHAR;
}

//------------------------------------------------------------------
StringCompare ONDXKey::Compare(const ONDXKey& rKey) const
{
	//	DBG_ASSERT(is(), "Falscher Indexzugriff");
	StringCompare eResult;

	if (getValue().isNull())
	{
		if (rKey.getValue().isNull() || (rKey.IsText(getDBType()) && !rKey.getValue().getString().getLength()))
			eResult = COMPARE_EQUAL;
		else
			eResult = COMPARE_LESS;
	}
	else if (rKey.getValue().isNull())
	{
		if (getValue().isNull() || (IsText(getDBType()) && !getValue().getString().getLength()))
			eResult = COMPARE_EQUAL;
		else
			eResult = COMPARE_GREATER;
	}
	else if (IsText(getDBType()))
	{
		sal_Int32 nRes = getValue().getString().compareTo(rKey.getValue());
		eResult = (nRes > 0) ? COMPARE_GREATER : (nRes == 0) ? COMPARE_EQUAL : COMPARE_LESS;
	}
	else
	{
		double m = getValue(),n = rKey.getValue();
		eResult = (m > n) ? COMPARE_GREATER : (n == m) ? COMPARE_EQUAL : COMPARE_LESS;
	}

	// Record vergleich, wenn Index !Unique
	if (eResult == COMPARE_EQUAL && nRecord && rKey.nRecord)
		eResult = (nRecord > rKey.nRecord) ? COMPARE_GREATER :
				  (nRecord == rKey.nRecord) ? COMPARE_EQUAL : COMPARE_LESS;

	return eResult;
}
// -----------------------------------------------------------------------------
void ONDXKey::setValue(const ORowSetValue& _rVal)
{
	xValue = _rVal;
}
// -----------------------------------------------------------------------------
const ORowSetValue& ONDXKey::getValue() const
{
	return xValue;
}
// -----------------------------------------------------------------------------
SvStream& connectivity::dbase::operator >> (SvStream &rStream, ONDXPagePtr& rPage)
{
	rStream >> rPage.nPagePos;
	return rStream;
}
// -----------------------------------------------------------------------------
SvStream& connectivity::dbase::operator << (SvStream &rStream, const ONDXPagePtr& rPage)
{
	rStream << rPage.nPagePos;
	return rStream;
}
// -----------------------------------------------------------------------------
//==================================================================
// ONDXPagePtr
//==================================================================
//------------------------------------------------------------------
ONDXPagePtr::ONDXPagePtr(const ONDXPagePtr& rRef)
			  :ONDXPageRef(rRef)
			  ,nPagePos(rRef.nPagePos)
{
}

//------------------------------------------------------------------
ONDXPagePtr::ONDXPagePtr(ONDXPage* pRefPage)
			  :ONDXPageRef(pRefPage)
			  ,nPagePos(0)
{
	if (pRefPage)
		nPagePos = pRefPage->GetPagePos();
}
//------------------------------------------------------------------
ONDXPagePtr& ONDXPagePtr::operator=(const ONDXPagePtr& rRef)
{
	ONDXPageRef::operator=(rRef);
	nPagePos = rRef.nPagePos;
	return *this;
}

//------------------------------------------------------------------
ONDXPagePtr& ONDXPagePtr::operator= (ONDXPage* pRef)
{
	ONDXPageRef::operator=(pRef);
	nPagePos = (pRef) ? pRef->GetPagePos() : 0;
	return *this;
}
// -----------------------------------------------------------------------------
static sal_uInt32 nValue;
//------------------------------------------------------------------
SvStream& connectivity::dbase::operator >> (SvStream &rStream, ONDXPage& rPage)
{
	rStream.Seek(rPage.GetPagePos() * PAGE_SIZE);
	rStream >> nValue >> rPage.aChild;
	rPage.nCount = sal_uInt16(nValue);

//	DBG_ASSERT(rPage.nCount && rPage.nCount < rPage.GetIndex().GetMaxNodes(), "Falscher Count");
	for (sal_uInt16 i = 0; i < rPage.nCount; i++)
		rPage[i].Read(rStream, rPage.GetIndex());
	return rStream;
}

//------------------------------------------------------------------
SvStream& connectivity::dbase::operator << (SvStream &rStream, const ONDXPage& rPage)
{
	// Seite existiert noch nicht
	sal_uIntPtr nSize = (rPage.GetPagePos() + 1) * PAGE_SIZE;
	if (nSize > rStream.Seek(STREAM_SEEK_TO_END))
	{
		rStream.SetStreamSize(nSize);
		rStream.Seek(rPage.GetPagePos() * PAGE_SIZE);

		char aEmptyData[PAGE_SIZE];
		memset(aEmptyData,0x00,PAGE_SIZE);
		rStream.Write((sal_uInt8*)aEmptyData,PAGE_SIZE);
	}
	sal_uIntPtr nCurrentPos = rStream.Seek(rPage.GetPagePos() * PAGE_SIZE);
    OSL_UNUSED( nCurrentPos );

	nValue = rPage.nCount;
	rStream << nValue << rPage.aChild;

	sal_uInt16 i = 0;
	for (; i < rPage.nCount; i++)
		rPage[i].Write(rStream, rPage);

	// check if we have to fill the stream with '\0'
	if(i < rPage.rIndex.getHeader().db_maxkeys)
	{
		sal_uIntPtr nTell = rStream.Tell() % PAGE_SIZE;
		sal_uInt16 nBufferSize = rStream.GetBufferSize();
		sal_uIntPtr nRemainSize = nBufferSize - nTell;
		if ( nRemainSize <= nBufferSize )
		{
			char* pEmptyData = new char[nRemainSize];
			memset(pEmptyData,0x00,nRemainSize);
			rStream.Write((sal_uInt8*)pEmptyData,nRemainSize);
			rStream.Seek(nTell);
			delete [] pEmptyData;
		}
	}
	return rStream;
}
// -----------------------------------------------------------------------------
#if OSL_DEBUG_LEVEL > 1
//------------------------------------------------------------------
void ONDXPage::PrintPage()
{
	DBG_TRACE4("\nSDB: -----------Page: %d  Parent: %d  Count: %d  Child: %d-----",
		nPagePos, HasParent() ? aParent->GetPagePos() : 0 ,nCount, aChild.GetPagePos());

	for (sal_uInt16 i = 0; i < nCount; i++)
	{
		ONDXNode rNode = (*this)[i];
		ONDXKey&  rKey = rNode.GetKey();
		if (!IsLeaf())
			rNode.GetChild(&rIndex, this);

		if (rKey.getValue().isNull())
		{
			DBG_TRACE2("SDB: [%d,NULL,%d]",rKey.GetRecord(), rNode.GetChild().GetPagePos());
		}
		else if (rIndex.getHeader().db_keytype)
		{
			DBG_TRACE3("SDB: [%d,%f,%d]",rKey.GetRecord(), rKey.getValue().getDouble(),rNode.GetChild().GetPagePos());
		}
		else
		{
			DBG_TRACE3("SDB: [%d,%s,%d]",rKey.GetRecord(), (const char* )ByteString(rKey.getValue().getString().getStr(), rIndex.m_pTable->getConnection()->getTextEncoding()).GetBuffer(),rNode.GetChild().GetPagePos());
		}
	}
	DBG_TRACE("SDB: -----------------------------------------------\n");
	if (!IsLeaf())
	{
#if OSL_DEBUG_LEVEL > 1
		GetChild(&rIndex)->PrintPage();
		for (sal_uInt16 i = 0; i < nCount; i++)
		{
			ONDXNode rNode = (*this)[i];
			rNode.GetChild(&rIndex,this)->PrintPage();
		}
#endif
	}
	DBG_TRACE("SDB: ===============================================\n");
}
#endif
// -----------------------------------------------------------------------------
sal_Bool ONDXPage::IsFull() const
{
	return Count() == rIndex.getHeader().db_maxkeys;
}
// -----------------------------------------------------------------------------
//------------------------------------------------------------------
sal_uInt16 ONDXPage::Search(const ONDXKey& rSearch)
{
	// binare Suche spaeter
	sal_uInt16 i = NODE_NOTFOUND;
	while (++i < Count())
		if ((*this)[i].GetKey() == rSearch)
			break;

	return (i < Count()) ? i : NODE_NOTFOUND;
}

//------------------------------------------------------------------
sal_uInt16 ONDXPage::Search(const ONDXPage* pPage)
{
	sal_uInt16 i = NODE_NOTFOUND;
	while (++i < Count())
		if (((*this)[i]).GetChild() == pPage)
			break;

	// wenn nicht gefunden, dann wird davon ausgegangen, dass die Seite selbst
	// auf die Page zeigt
	return (i < Count()) ? i : NODE_NOTFOUND;
}
// -----------------------------------------------------------------------------
// laeuft rekursiv
void ONDXPage::SearchAndReplace(const ONDXKey& rSearch,
								  ONDXKey& rReplace)
{
	OSL_ENSURE(rSearch != rReplace,"Invalid here:rSearch == rReplace");
	if (rSearch != rReplace)
	{
		sal_uInt16 nPos = NODE_NOTFOUND;
		ONDXPage* pPage = this;

		while (pPage && (nPos = pPage->Search(rSearch)) == NODE_NOTFOUND)
			pPage = pPage->aParent;

		if (pPage)
		{
			(*pPage)[nPos].GetKey() = rReplace;
			pPage->SetModified(sal_True);
		}
	}
}
// -----------------------------------------------------------------------------
ONDXNode& ONDXPage::operator[] (sal_uInt16 nPos)
{
	DBG_ASSERT(nCount > nPos, "falscher Indexzugriff");
	return ppNodes[nPos];
}

//------------------------------------------------------------------
const ONDXNode& ONDXPage::operator[] (sal_uInt16 nPos) const
{
	DBG_ASSERT(nCount > nPos, "falscher Indexzugriff");
	return ppNodes[nPos];
}
// -----------------------------------------------------------------------------
void ONDXPage::Remove(sal_uInt16 nPos)
{
	DBG_ASSERT(nCount > nPos, "falscher Indexzugriff");

	for (sal_uInt16 i = nPos; i < (nCount-1); i++)
		(*this)[i] = (*this)[i+1];

	nCount--;
	bModified = sal_True;
}
// -----------------------------------------------------------------------------

