ByteString DataDocumentManager::getDocument(int ID)
{
	ByteString recordString;
	ByteString byteString;
	byteString.insertLast(&ID,sizeof(int));
	string idString = byteString.toString();
	Key key(idString);
	pair<Record*, BPlusTreeIterator*> searchResult = this->principalIndex->search(key);
	if(searchResult.first != NULL)
	{
		int position = searchResult.first->getData()->readAsInt(0);
		if(position > -1)
		{
			recordString = this->fileVariableRecord->readDocument(position);
		}

		//delete poddo
		delete searchResult.first;
	}

	//delete poddo
	if (searchResult.second != NULL)
		delete searchResult.second;

	return recordString;
}
bool DataDocumentManager::removeRecord(int ID)
{
	bool deleted = false;
	ByteString byteString;
	byteString.insertLast(&ID,sizeof(int));
	string idString = byteString.toString();
	Key key(idString);
	pair<Record*, BPlusTreeIterator*> searchResult = this->principalIndex->search(key);
	if(searchResult.first != NULL)
	{
		int position = searchResult.first->getData()->readAsInt(0);
		if(position > -1)
		{
			this->fileVariableRecord->deleteDocument(position);
			this->principalIndex->removeKey(key);
			ByteString bs(key.toString());
			removeIDtoFileFlags(IndexWrapper::AUTOR,bs.readAsInt(0));
			removeIDtoFileFlags(IndexWrapper::TITULO,bs.readAsInt(0));
			removeIDtoFileFlags(IndexWrapper::PALABRAS,bs.readAsInt(0));
			removeIDtoFileFlags(IndexWrapper::IDENTIFICADOR,bs.readAsInt(0));
			removeIDtoFileFlags(IndexWrapper::FECHA,bs.readAsInt(0));
			deleted = true;
		}
	}
	return deleted;
}
list<int>* Mediator::getListOfPositions(int idBook, int idTerm)
{
	//busca la lista de ocurrencias de un termino en un libro
	ByteString* bs = new ByteString();
	bs->insertLast(&idBook,sizeof(int));
	bs->insertLast(&idTerm,sizeof(int));
	string clave = bs->toString();
	delete bs;

	Key* k = new Key(clave);
	list<int>* listOfPos = this->ocurrenceTree->searchAllIds(*k);
	delete k;

	return listOfPos;
}
int Mediator::getInfinityNorm(int idBook)
{
	//busca la norma infinito
	ByteString* bsId = new ByteString();
	bsId->insertLast(&idBook,sizeof(int));
	string clave = bsId->toString();
	delete bsId;

	Key* keyIdBook = new Key(clave);
	pair<Record*, BPlusTreeIterator*> searchResult = this->infinityNormIndex->search(*keyIdBook);
	int infinityNorm = searchResult.first->getData()->readAsInt(0);
	delete searchResult.first;
	delete searchResult.second;
	delete keyIdBook;

	return infinityNorm;
}
bool DataDocumentManager::addDocument(ByteString byteString)
{
	bool saved = false;
	int realID = this->autoIncInteger + 1;
	int documentID;
	string sid = Utility::intToString(realID);
	string did;

	Document document;
	document.Hidratate(byteString);
	document.setFakeId(realID);
	if(document.getTitle()[0] == 'T')
		documentID = this->twtautoIncInteger + 1;
	else if(document.getTitle()[0] == 'N')
		documentID = this->rssautoIncInteger + 1;
	did = Utility::intToString(documentID);
	document.setIdentificador(Utility::concat(document.getTitle(), did));

	int position = this->fileVariableRecord->addDocument(document.Serialize());
	if(position > -1)
	{
		this->autoIncInteger++;
		if(document.getTitle()[0] == 'N')
			rssautoIncInteger++;
		else if(document.getTitle()[0] == 'T')
			twtautoIncInteger++;
		ByteString idDocument;
		idDocument.insertLast(&realID, sizeof(int));
		Key* key = new Key(idDocument.toString());
		ByteString offset;
		offset.insertLast(&position, sizeof(int));
		Record* recPrincipalInd = new Record(key,&offset);
		this->principalIndex->add(recPrincipalInd);
		addIDtoFileFlags(IndexWrapper::AUTOR,idDocument.readAsInt(0));
		addIDtoFileFlags(IndexWrapper::TITULO,idDocument.readAsInt(0));
		addIDtoFileFlags(IndexWrapper::PALABRAS,idDocument.readAsInt(0));
		addIDtoFileFlags(IndexWrapper::IDENTIFICADOR,idDocument.readAsInt(0));
		addIDtoFileFlags(IndexWrapper::FECHA,idDocument.readAsInt(0));

		saved = true;
	}
	return saved;
}
void BPlusTree::exportNode(ofstream& salida, Node* unNodo, int tabulacion,bool keyText,bool textContent) {

	if (unNodo->isLeaf()) {

		LeafNode *unNodoHoja = static_cast<LeafNode*> (unNodo);
		salida << endl;
		for(int i = 0 ; i < tabulacion ; i++)
			salida << "  ";

		salida << "Numero: " << unNodoHoja->number << "  Nivel: " << unNodoHoja->level << "  Cant.Elem: " << unNodoHoja->keyMount
			   << "  Esp.Libre: " << TreeConstraits::getEfectiveSizeNode() - unNodoHoja->occupiedSpace << "  Hoja.Sig: " << unNodoHoja->nextLeaf << endl;

		for (int posicion = 0; posicion < unNodoHoja->keyMount; ++posicion) {

			for(int i = 0 ; i < tabulacion + 4 ; i++)
						salida << "  ";

			salida << "(";

			Key unaClave = unNodoHoja->keys[posicion];
			if(keyText)
			{
				salida << unaClave.toString();
			}
			else
			{
				ByteString clave(unaClave.toString());
				salida << Utility::toString(clave.readAsInt(0));
			}

			salida << ";";
			ByteString unDato = unNodoHoja->byteData[posicion];
			if(textContent)
			{
				salida << unDato.toString();
			}
			else
			{
				salida << Utility::intToString(unDato.readAsInt(0));
			}

			salida << ")";

			salida << (unaClave.getSize() + unDato.getSize() + TreeConstraits::getControlSizeRecord()) << endl;
		}

		salida << endl;

	} else {

		InnerNode *unNodoInterior = static_cast<InnerNode*> (unNodo);
		salida << endl << endl;
		for(int i=0; i<tabulacion ; i++)
			salida << "  ";

		salida << "Numero: " << unNodoInterior->number << "  Nivel: " << unNodoInterior->level << "  Cant.Elem: " << unNodoInterior->keyMount
			   << "  Esp.Libre: " << TreeConstraits::getEfectiveSizeNode() - unNodoInterior->occupiedSpace << endl;

		for (int posicion = 0; posicion <= unNodoInterior->keyMount; ++posicion) {

			if (posicion < unNodoInterior->keyMount) {
				Key unaClave = unNodoInterior->keys[posicion];

				for(int i=0; i<(tabulacion+1) ; i++)
					salida << "  ";
				salida << "(";
				if(keyText)
				{
					salida << unaClave.toString();
				}
				else
				{
					ByteString clave(unaClave.toString());
					salida << Utility::toString(clave.readAsInt(0));
				}
				salida << ")";
				salida << unaClave.getSize();
				salida << "  ";
				salida << unNodoInterior->getSons()[posicion] << "   ";
			}
		}
		for (int posicion = 0; posicion <= unNodoInterior->keyMount; ++posicion) {
			Node *hijo = hidratateNode(unNodoInterior->sons[posicion]);
			exportNode(salida, hijo, tabulacion + 2,keyText,textContent);
			if (hijo)
				freeNodeMemory(hijo);
		}
		for(int i=0; i<tabulacion ; i++)
			salida << "  ";
		salida << endl;
	}
}
bool Mediator::indexingListOnIndex(IndexWrapper::indexItem item)
{
	bool done = false;
	List<int>* flagsLs = this->dataBookManager->getListToFileFlag(item);
	if(!flagsLs->isEmpty())
	{
		cout << "Process Started: " << Utility::getDate() << endl;
		ListIterator<int> it = flagsLs->getIterator();
		int ID;
		while(it.hasNext())
		{
			ID = it.next();
			ByteString bs = this->dataBookManager->getBook(ID);
			Book book;
			book.Hidratate(bs);

			string clave;
			Record* record;
			ByteString bsIdBook;
			ByteString* bsId;
			bsIdBook.insertLast(&ID,sizeof(int));
			Key* key;
			switch(item){
			case IndexWrapper::AUTOR :
										clave = book.getAuthor();
										cout << "Book begin process: " << book.getTitle() << " - Author:" << clave << " - Start:" << Utility::getDate();

										key = new Key(clave);
										bsId = new ByteString(bsIdBook);
										record = new Record(key,bsId);
										done = this->indexWrapper->add(record,item);
										break;
			case IndexWrapper::EDITORIAL :
										clave = book.getEditorial();
										cout << "Book begin process: " << book.getTitle() << " - Editorial:" << clave << " - Start:" << Utility::getDate();

										key = new Key(clave);
										bsId = new ByteString(bsIdBook);
										record = new Record(key,bsId);
										done = this->indexWrapper->add(record,item);
										break;
			case IndexWrapper::TITULO :
										clave = book.getTitle();
										cout << "Book begin process: " << book.getTitle() << " - Start:" << Utility::getDate();

										key = new Key(clave);
										bsId = new ByteString(bsIdBook);
										record = new Record(key,bsId);
										done = this->indexWrapper->add(record,item);
										break;
			case IndexWrapper::PALABRAS :
										this->fileParser->setWords(book.getText());

										// ----------------------------------------------------------------------------------------------- //
										// Se incorpora la norma infinito del documento
										// ----------------------------------------------------------------------------------------------- //
										Key* keyIdBook = new Key(bsIdBook.toString());

										ByteString* bsInfinityNorm = new ByteString();
										unsigned int infinityNorm = this->fileParser->getInfinityNorm();
										bsInfinityNorm->insertLast(&infinityNorm, sizeof(unsigned int));

										Record* recInfinityNorm = new Record(keyIdBook, bsInfinityNorm);
										this->infinityNormIndex->add(recInfinityNorm);
										delete recInfinityNorm;
										// ----------------------------------------------------------------------------------------------- //

										map<string,Term*> terms = this->fileParser->getTerms();
										cout << "Book begin process: " << book.getTitle() << " - Words Count:" << Utility::intToString(terms.size()) << " - Start:" << Utility::getDate();
										int i = 0;
										for(map<string,Term*>::iterator it = terms.begin(); it != terms.end(); ++it)
										{
											i++;
											// ------------------------ //
											key = new Key(it->first);
											string word = it->first;
											list<int>* listDocuments = this->indexWrapper->searchAllIds(key, IndexWrapper::PALABRAS);
											int idTerm;

											// Si no tiene datos --> la palabra no existe en el hash
											if (listDocuments->size() == 0)
											{
												//delete poddo
												delete listDocuments;

												// Se agrega la palabra al vocabulario y se obtiene su id
												int possibleID = this->autoIncInteger + 1;

												// La clave es el id de termino y el dato la palabra
												ByteString bsIdTerm;
												bsIdTerm.insertLast(&possibleID, sizeof(int));
												Key* keyIdTerm = new Key(bsIdTerm.toString());

												ByteString* bsTerm = new ByteString();
												bsTerm->insertLast(word);

												Record* recVocabulary = new Record(keyIdTerm, bsTerm);
												this->vocabularyIndex->add(recVocabulary);
												delete recVocabulary;

												idTerm = possibleID;
												this->autoIncInteger++;
											}
											else
											{
												// Devuelve en la ultima posicion el id del termino y en las restantes los id de documentos
												Word* newWord = new Word(word, listDocuments);
												idTerm = newWord->getIdWord();
												delete newWord; // se elimina la lisdDocuments tambien
											}

											//Aca se agrega las ocurrencias del termino en el libro
											list<unsigned int> listOfPositions = it->second->getPositions();

											ByteString bs;
											bs.insertLast(&ID,sizeof(int));
											bs.insertLast(&idTerm,sizeof(int));
											Record* r = new Record();
											r->setKey(new Key(bs.toString()));

											this->ocurrenceTree->addList(r,listOfPositions);

											listOfPositions.clear();
											delete r;

											// ------------------------ //
											bsId = new ByteString(bsIdBook);
											bsId->insertLast(&idTerm, sizeof(int));
											record = new Record(key,bsId);

											done = this->indexWrapper->add(record,item);
											delete record;
										}

										break;
			}
			cout << "Book processed: " << book.getTitle() << " - Finish:" << Utility::getDate() << endl;
		}
		cout << "Process Ended: " << Utility::getDate();
	}

	//delete poddo
	if (flagsLs != NULL)
		delete flagsLs;

	return done;
}
void ClassifBPlusTree::exportNode(ofstream& salida, Node* unNodo, int tabulacion,bool keytext, bool textContent) {

	if (unNodo->isLeaf()) {

		LeafNode *unNodoHoja = static_cast<LeafNode*> (unNodo);
		salida << endl;
		for(int i = 0 ; i < tabulacion ; i++)
			salida << "  ";

		salida << "Numero: " << unNodoHoja->number << "  Nivel: " << unNodoHoja->level << "  Cant.Elem: " << unNodoHoja->keyMount << "  Esp.Libre: " << TreeConstraits::getEfectiveSizeNode() - unNodoHoja->occupiedSpace << "  Hoja.Sig: " << unNodoHoja->nextLeaf << endl;

		for (int posicion = 0; posicion < unNodoHoja->keyMount; ++posicion) {

			for(int i = 0 ; i < tabulacion + 4 ; i++)
						salida << "  ";

			salida << "(";

			Key unaClave = unNodoHoja->keys[posicion];
			if(keytext)
			{
				salida << unaClave.toString();
			}
			else
			{
				ByteString clave(unaClave.toString());
				if(clave.getSize()==(2*sizeof(int)))
				{
					salida << Utility::toString(clave.readAsInt(0));
					salida << "-";
					salida << Utility::toString(clave.readAsInt(sizeof(int)));
				}
				else
					salida << Utility::toString(clave.readAsInt(0));
			}

			salida << ";";

			ByteString unDato = unNodoHoja->byteData[posicion];

			int idBlock = unDato.readAsInt(0);
			string datoString = Utility::intToString(idBlock);
			salida << datoString;

			salida << ")";

			salida << (unaClave.getSize() + unDato.getSize() + TreeConstraits::getControlSizeRecord()) << endl;

			for(int i = 0 ; i < tabulacion + 4 ; i++)
								salida << "  ";

			ListofID listOfID(this->fileBlockManager,idBlock);
			list<int> listOfInt = listOfID.getListID();
			list<int>::iterator it;

			int id;
			//int count = 0;
			ByteString bs;
			unsigned int i = 0;
			for(it=listOfInt.begin();it!=listOfInt.end();++it)
			{
				i++;
				id = *it;
				bs.insertLast(Utility::intToString(id));
				bs.insertLast(" ");
				if((i == listOfInt.size()) || (bs.toString().size() >80))
				{
					salida << bs.toString();
					salida << endl;
					if(i != listOfInt.size())
					{
						for(int i = 0 ; i < tabulacion + 4 ; i++)
											salida << "  ";
					}
					bs.clean();
				}
			}

		}

	} else {

		InnerNode *unNodoInterior = static_cast<InnerNode*> (unNodo);
		salida << endl << endl;
		for(int i=0; i<tabulacion ; i++)
			salida << "  ";

		salida << "Numero: " << unNodoInterior->number << "  Nivel: " << unNodoInterior->level << "  Cant.Elem: " << unNodoInterior->keyMount
			   << "  Esp.Libre: " << TreeConstraits::getEfectiveSizeNode() - unNodoInterior->occupiedSpace << endl;

		for (int posicion = 0; posicion <= unNodoInterior->keyMount; ++posicion) {

			if (posicion < unNodoInterior->keyMount) {
				Key unaClave = unNodoInterior->keys[posicion];

				for(int i=0; i<(tabulacion+1) ; i++)
					salida << "  ";
				salida << "(";
				if(keytext)
				{
					salida << unaClave.toString();
				}
				else
				{
					ByteString clave(unaClave.toString());
					salida << Utility::toString(clave.readAsInt(0));
				}
				salida << ")";
				salida << unaClave.getSize();
				salida << "  ";
				salida << unNodoInterior->getSons()[posicion] << "   ";
			}
		}
		for (int posicion = 0; posicion <= unNodoInterior->keyMount; ++posicion) {
			Node *hijo = hidratateNode(unNodoInterior->sons[posicion]);
			exportNode(salida, hijo, tabulacion + 2,keytext,textContent);
			if (hijo)
				freeNodeMemory(hijo);
		}
		for(int i=0; i<tabulacion ; i++)
			salida << "  ";
		salida << endl;
	}
}