/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.core.index;

import java.io.*;

import org.eclipse.jdt.core.search.*;
import org.eclipse.jdt.internal.core.util.*;
import org.eclipse.jdt.internal.compiler.util.HashtableOfIntValues;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;

public class DiskIndex {

String fileName;

private int headerInfoOffset;
private int numberOfChunks;
private int sizeOfLastChunk;
private int[] chunkOffsets;
private int documentReferenceSize; // 1, 2 or more bytes... depends on # of document names
private HashtableOfIntValues categoryOffsets;

private int cacheUserCount;
private String[][] cachedChunks; // decompressed chunks of document names
private HashtableOfObject categoryTables; // category name -> HashtableOfObject(words -> int[] of document #'s) or offset if not read yet

public static final String SIGNATURE= "INDEX VERSION 1.011"; //$NON-NLS-1$
public static boolean DEBUG = false;

private static final int RE_INDEXED = -1;
private static final int DELETED = -2;

private static final int CHUNK_SIZE = 100;

class IntList {

int size;
int[] elements;

IntList(int[] elements) {
	this.elements = elements;
	this.size = elements.length;
}
void add(int newElement) {
	if (this.size == this.elements.length) {
		int newSize = this.size * 3;
		if (newSize < 7) newSize = 7;
		System.arraycopy(this.elements, 0, this.elements = new int[newSize], 0, this.size);
	}
	this.elements[this.size++] = newElement;
}
int[] asArray() {
	int[] result = new int[this.size];
	System.arraycopy(this.elements, 0, result, 0, this.size);
	return result;
}	
}


DiskIndex(String fileName) {
	this.fileName = fileName;

	// clear cached items
	this.headerInfoOffset = -1;
	this.numberOfChunks = -1;
	this.sizeOfLastChunk = -1;
	this.chunkOffsets = null;
	this.documentReferenceSize = -1;
	this.cacheUserCount = -1;
	this.cachedChunks = null;
	this.categoryTables = null;
	this.categoryOffsets = null;
}
SimpleSet addDocumentNames(String substring, MemoryIndex memoryIndex) throws IOException {
	// must skip over documents which have been added/changed/deleted in the memory index
	String[] docNames = readAllDocumentNames();
	SimpleSet results = new SimpleSet(docNames.length);
	if (substring == null) {
		if (memoryIndex == null) {
			for (int i = 0, l = docNames.length; i < l; i++)
				results.add(docNames[i]);
		} else {
			SimpleLookupTable docsToRefs = memoryIndex.docsToReferences;
			for (int i = 0, l = docNames.length; i < l; i++) {
				String docName = docNames[i];
				if (!docsToRefs.containsKey(docName))
					results.add(docName);
			}
		}
	} else {
		if (memoryIndex == null) {
			for (int i = 0, l = docNames.length; i < l; i++)
				if (docNames[i].startsWith(substring, 0))
					results.add(docNames[i]);
		} else {
			SimpleLookupTable docsToRefs = memoryIndex.docsToReferences;
			for (int i = 0, l = docNames.length; i < l; i++) {
				String docName = docNames[i];
				if (docName.startsWith(substring, 0) && !docsToRefs.containsKey(docName))
					results.add(docName);
			}
		}
	}
	return results;
}
private void addQueryResult(HashtableOfObject results, char[] word, HashtableOfObject wordsToDocNumbers, MemoryIndex memoryIndex) throws IOException {
	// must skip over documents which have been added/changed/deleted in the memory index
	EntryResult result = (EntryResult) results.get(word);
	if (memoryIndex == null) {
		if (result == null)
			results.put(word, new EntryResult(word, wordsToDocNumbers));
		else
			result.addDocumentTable(wordsToDocNumbers);
	} else {
		SimpleLookupTable docsToRefs = memoryIndex.docsToReferences;
		if (result == null)
			result = new EntryResult(word, null);
		int[] docNumbers = readDocumentNumbers(wordsToDocNumbers.get(word));
		for (int i = 0, l = docNumbers.length; i < l; i++) {
			String docName = readDocumentName(docNumbers[i]);
			if (!docsToRefs.containsKey(docName))
				result.addDocumentName(docName);
		}
		if (!result.isEmpty())
			results.put(word, result);
	}
}
HashtableOfObject addQueryResults(char[][] categories, char[] key, int matchRule, MemoryIndex memoryIndex) throws IOException {
	// assumes sender has called startQuery() & will call stopQuery() when finished
	HashtableOfObject results = new HashtableOfObject(13);
	if (this.categoryOffsets == null)
		return results; // file is empty

	if (matchRule == SearchPattern.R_EXACT_MATCH + SearchPattern.R_CASE_SENSITIVE) {
		for (int i = 0, l = categories.length; i < l; i++) {
			HashtableOfObject wordsToDocNumbers = readCategoryTable(categories[i], false);
			if (wordsToDocNumbers != null && wordsToDocNumbers.containsKey(key))
				addQueryResult(results, key, wordsToDocNumbers, memoryIndex);
		}
	} else {
		for (int i = 0, l = categories.length; i < l; i++) {
			HashtableOfObject wordsToDocNumbers = readCategoryTable(categories[i], false);
			if (wordsToDocNumbers != null) {
				char[][] words = wordsToDocNumbers.keyTable;
				for (int j = 0, m = words.length; j < m; j++) {
					char[] word = words[j];
					if (word != null && Index.isMatch(key, word, matchRule))
						addQueryResult(results, word, wordsToDocNumbers, memoryIndex);
				}
			}
		}
	}
	return results;
}
private String[] computeDocumentNames(String[] onDiskNames, int[] positions, SimpleLookupTable indexedDocuments, MemoryIndex memoryIndex) {
	int onDiskLength = onDiskNames.length;
	Object[] docNames = memoryIndex.docsToReferences.keyTable;
	Object[] referenceTables = memoryIndex.docsToReferences.valueTable;
	if (onDiskLength == 0) {
		// disk index was empty, so add every indexed document
		for (int i = 0, l = referenceTables.length; i < l; i++)
			if (referenceTables[i] != null)
				indexedDocuments.put(docNames[i], null); // remember each new document

		String[] newDocNames = new String[indexedDocuments.elementSize];
		int count = 0;
		Object[] added = indexedDocuments.keyTable;
		for (int i = 0, l = added.length; i < l; i++)
			if (added[i] != null)
				newDocNames[count++] = (String) added[i];
		Util.sort(newDocNames);
		for (int i = 0, l = newDocNames.length; i < l; i++)
			indexedDocuments.put(newDocNames[i], new Integer(i));
		return newDocNames;
	}

	// initialize positions as if each document will remain in the same position
	for (int i = 0; i < onDiskLength; i++)
		positions[i] = i;

	// find out if the memory index has any new or deleted documents, if not then the names & positions are the same
	int numDeletedDocNames = 0;
	int numReindexedDocNames = 0;
	nextPath : for (int i = 0, l = docNames.length; i < l; i++) {
		String docName = (String) docNames[i];
		if (docName != null) {
			for (int j = 0; j < onDiskLength; j++) {
				if (docName.equals(onDiskNames[j])) {
					if (referenceTables[i] == null) {
						positions[j] = DELETED;
						numDeletedDocNames++;
					} else {
						positions[j] = RE_INDEXED;
						numReindexedDocNames++;
					}
					continue nextPath;
				}
			}
			if (referenceTables[i] != null)
				indexedDocuments.put(docName, null); // remember each new document, skip deleted documents which were never saved
		}
	}

	String[] newDocNames = onDiskNames;
	if (numDeletedDocNames > 0 || indexedDocuments.elementSize > 0) {
		// some new documents have been added or some old ones deleted
		newDocNames = new String[onDiskLength + indexedDocuments.elementSize - numDeletedDocNames];
		int count = 0;
		for (int i = 0; i < onDiskLength; i++)
			if (positions[i] >= RE_INDEXED)
				newDocNames[count++] = onDiskNames[i]; // keep each unchanged document
		Object[] added = indexedDocuments.keyTable;
		for (int i = 0, l = added.length; i < l; i++)
			if (added[i] != null)
				newDocNames[count++] = (String) added[i]; // add each new document
		Util.sort(newDocNames);
		for (int i = 0, l = newDocNames.length; i < l; i++)
			if (indexedDocuments.containsKey(newDocNames[i]))
				indexedDocuments.put(newDocNames[i], new Integer(i)); // remember the position for each new document
	}

	// need to be able to look up an old position (ref# from a ref[]) and map it to its new position
	// if its old position == DELETED then its forgotton
	// if its old position == ReINDEXED then its also forgotten but its new position is needed to map references
	int count = -1;
	for (int i = 0; i < onDiskLength;) {
		switch(positions[i]) {
			case DELETED :
				i++; // skip over deleted... references are forgotten
				break;
			case RE_INDEXED :
				String newName = newDocNames[++count];
				if (newName.equals(onDiskNames[i])) {
					indexedDocuments.put(newName, new Integer(count)); // the reindexed docName that was at position i is now at position count
					i++;
				}
				break;
			default :
				if (newDocNames[++count].equals(onDiskNames[i]))
					positions[i++] = count; // the unchanged docName that was at position i is now at position count
		}
	}
	return newDocNames;
}
private void copyQueryResults(HashtableOfObject categoryToWords, int newPosition) {
	char[][] categoryNames = categoryToWords.keyTable;
	Object[] wordSets = categoryToWords.valueTable;
	for (int i = 0, l = categoryNames.length; i < l; i++) {
		char[] categoryName = categoryNames[i];
		if (categoryName != null) {
			SimpleWordSet wordSet = (SimpleWordSet) wordSets[i];
			HashtableOfObject wordsToDocs = (HashtableOfObject) this.categoryTables.get(categoryName);
			if (wordsToDocs == null)
				this.categoryTables.put(categoryName, wordsToDocs = new HashtableOfObject(wordSet.elementSize));

			char[][] words = wordSet.words;
			for (int j = 0, m = words.length; j < m; j++) {
				char[] word = words[j];
				if (word != null) {
					Object o = wordsToDocs.get(word);
					if (o == null) {
						wordsToDocs.put(word, new int[] {newPosition});
					} else if (o instanceof IntList) {
						((IntList) o).add(newPosition);
					} else {
						IntList list = new IntList((int[]) o);
						list.add(newPosition);
						wordsToDocs.put(word, list);
					}
				}
			}
		}
	}
}
File getIndexFile() {
	if (this.fileName == null) return null;

	return new File(this.fileName);
}
void initialize(boolean reuseExistingFile) throws IOException {
	File indexFile = getIndexFile();
	if (indexFile.exists()) {
		if (reuseExistingFile) {
			RandomAccessFile file = new RandomAccessFile(this.fileName, "r"); //$NON-NLS-1$
			try {
				String signature = file.readUTF();
				if (!signature.equals(SIGNATURE))
					throw new IOException(Util.bind("exception.wrongFormat")); //$NON-NLS-1$

				this.headerInfoOffset = file.readInt();
				if (this.headerInfoOffset > 0) // file is empty if its not set
					readHeaderInfo(file);
			} finally {
				file.close();
			}
			return;
		}
		if (!indexFile.delete()) {
			if (DEBUG)
				System.out.println("initialize - Failed to delete index " + this.fileName); //$NON-NLS-1$
			throw new IOException("Failed to delete index " + this.fileName); //$NON-NLS-1$
		}
	}
	if (indexFile.createNewFile()) {
		RandomAccessFile file = new RandomAccessFile(this.fileName, "rw"); //$NON-NLS-1$
		try {
			file.writeUTF(SIGNATURE);
			file.writeInt(-1); // file is empty
		} finally {
			file.close();
		}
	} else {
		if (DEBUG)
			System.out.println("initialize - Failed to create new index " + this.fileName); //$NON-NLS-1$
		throw new IOException("Failed to create new index " + this.fileName); //$NON-NLS-1$
	}
}
private void initializeFrom(DiskIndex diskIndex, File newIndexFile) throws IOException {
	if (newIndexFile.exists() && !newIndexFile.delete()) { // delete the temporary index file
		if (DEBUG)
			System.out.println("initializeFrom - Failed to delete temp index " + this.fileName); //$NON-NLS-1$
	} else if (!newIndexFile.createNewFile()) {
		if (DEBUG)
			System.out.println("initializeFrom - Failed to create temp index " + this.fileName); //$NON-NLS-1$
		throw new IOException("Failed to create temp index " + this.fileName); //$NON-NLS-1$
	}

	int size = diskIndex.categoryOffsets == null ? 8 : diskIndex.categoryOffsets.elementSize;
	this.categoryOffsets = new HashtableOfIntValues(size);
	this.categoryTables = new HashtableOfObject(size);
}
private void mergeCategories(DiskIndex onDisk, int[] positions, DataOutputStream stream) throws IOException {
	// at this point, this.categoryTables contains the names -> wordsToDocs added in copyQueryResults()
	char[][] oldNames = onDisk.categoryOffsets.keyTable;
	for (int i = 0, l = oldNames.length; i < l; i++) {
		char[] oldName = oldNames[i];
		if (oldName != null && !this.categoryTables.containsKey(oldName))
			this.categoryTables.put(oldName, null);
	}

	char[][] categoryNames = this.categoryTables.keyTable;
	for (int i = 0, l = categoryNames.length; i < l; i++)
		if (categoryNames[i] != null)
			mergeCategory(categoryNames[i], onDisk, positions, stream);
	this.categoryTables = null;
}
private void mergeCategory(char[] categoryName, DiskIndex onDisk, int[] positions, DataOutputStream stream) throws IOException {
	HashtableOfObject wordsToDocs = (HashtableOfObject) this.categoryTables.get(categoryName);
	if (wordsToDocs == null)
		wordsToDocs = new HashtableOfObject(3);

	HashtableOfObject oldWordsToDocs = onDisk.readCategoryTable(categoryName, true);
	if (oldWordsToDocs != null) {
		char[][] oldWords = oldWordsToDocs.keyTable;
		Object[] oldArrayOffsets = oldWordsToDocs.valueTable;
		nextWord: for (int i = 0, l = oldWords.length; i < l; i++) {
			char[] oldWord = oldWords[i];
			if (oldWord != null) {
				int[] oldDocNumbers = (int[]) oldArrayOffsets[i];
				int length = oldDocNumbers.length;
				int[] mappedNumbers = new int[length];
				int count = 0;
				for (int j = 0; j < length; j++) {
					int pos = positions[oldDocNumbers[j]];
					if (pos > RE_INDEXED) // forget any reference to a document which was deleted or re_indexed
						mappedNumbers[count++] = pos;
				}
				if (count < length) {
					if (count == 0) continue nextWord; // skip words which no longer have any references
					System.arraycopy(mappedNumbers, 0, mappedNumbers = new int[count], 0, count);
				}

				Object o = wordsToDocs.get(oldWord);
				if (o == null) {
					wordsToDocs.put(oldWord, mappedNumbers);
				} else {
					IntList list = null;
					if (o instanceof IntList) {
						list = (IntList) o;
					} else {
						list = new IntList((int[]) o);
						wordsToDocs.put(oldWord, list);
					}
					for (int j = 0; j < count; j++)
						list.add(mappedNumbers[j]);
				}
			}
		}
		onDisk.categoryTables.put(categoryName, null); // flush cached table
	}
	writeCategoryTable(categoryName, wordsToDocs, stream);
}
DiskIndex mergeWith(MemoryIndex memoryIndex) throws IOException {
 	// assume write lock is held
	// compute & write out new docNames
	String[] docNames = readAllDocumentNames();
	int previousLength = docNames.length;
	int[] positions = new int[previousLength]; // keeps track of the position of each document in the new sorted docNames
	SimpleLookupTable indexedDocuments = new SimpleLookupTable(3); // for each new/changed document in the memoryIndex
	docNames = computeDocumentNames(docNames, positions, indexedDocuments, memoryIndex);
	if (docNames.length == 0) {
		if (previousLength == 0) return this; // nothing to do... memory index contained deleted documents that had never been saved

		// index is now empty since all the saved documents were removed
		DiskIndex newDiskIndex = new DiskIndex(this.fileName);
		newDiskIndex.initialize(false);
		return newDiskIndex;
	}

	DiskIndex newDiskIndex = new DiskIndex(this.fileName + ".tmp"); //$NON-NLS-1$
	File newIndexFile = newDiskIndex.getIndexFile();
	try {
		newDiskIndex.initializeFrom(this, newIndexFile);
		DataOutputStream stream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(newIndexFile, false), 2048));
		int offsetToHeader = -1;
		try {
			newDiskIndex.writeAllDocumentNames(docNames, stream);
			docNames = null; // free up the space

			// add each new/changed doc to empty category tables using its new position #
			if (indexedDocuments.elementSize > 0) {
				Object[] names = indexedDocuments.keyTable;
				Object[] integerPositions = indexedDocuments.valueTable;
				for (int i = 0, l = names.length; i < l; i++)
					if (names[i] != null)
						newDiskIndex.copyQueryResults(
							(HashtableOfObject) memoryIndex.docsToReferences.get(names[i]),
							((Integer) integerPositions[i]).intValue());
			}
			indexedDocuments = null; // free up the space

			// merge each category table with the new ones & write them out
			if (previousLength == 0)
				newDiskIndex.writeCategories(stream);
			else
				newDiskIndex.mergeCategories(this, positions, stream);
			offsetToHeader = stream.size();
			newDiskIndex.writeHeaderInfo(stream);
			positions = null; // free up the space
		} finally {
			stream.close();
		}
		newDiskIndex.writeOffsetToHeader(offsetToHeader);

		// rename file by deleting previous index file & renaming temp one
		File old = getIndexFile();
		if (!old.delete()) {
			if (DEBUG)
				System.out.println("mergeWith - Failed to delete " + this.fileName); //$NON-NLS-1$
			throw new IOException("Failed to delete index file " + this.fileName); //$NON-NLS-1$
		}
		if (!newIndexFile.renameTo(old)) {
			if (DEBUG)
				System.out.println("mergeWith - Failed to rename " + this.fileName); //$NON-NLS-1$
			throw new IOException("Failed to rename index file " + this.fileName); //$NON-NLS-1$
		}
	} catch (IOException e) {
		if (newIndexFile.exists() && !newIndexFile.delete())
			if (DEBUG)
				System.out.println("mergeWith - Failed to delete temp index " + newDiskIndex.fileName); //$NON-NLS-1$
		throw e;
	}

	newDiskIndex.fileName = this.fileName;
	return newDiskIndex;
}
private synchronized String[] readAllDocumentNames() throws IOException {
	if (this.numberOfChunks <= 0)
		return new String[0];

	DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(getIndexFile()), 2048));
	try {
		stream.skip(this.chunkOffsets[0]);
		int lastIndex = this.numberOfChunks - 1;
		String[] docNames = new String[lastIndex * CHUNK_SIZE + sizeOfLastChunk];
		for (int i = 0; i < this.numberOfChunks; i++)
			readChunk(docNames, stream, i * CHUNK_SIZE, i < lastIndex ? CHUNK_SIZE : sizeOfLastChunk);
		return docNames;
	} finally {
		stream.close();
	}
}
private synchronized HashtableOfObject readCategoryTable(char[] categoryName, boolean cacheDocNumbers) throws IOException {
	// result will be null if categoryName is unknown
	int offset = this.categoryOffsets.get(categoryName);
	if (offset == HashtableOfIntValues.NO_VALUE)
		return null;

	if (this.categoryTables == null) {
		this.categoryTables = new HashtableOfObject(this.categoryOffsets.elementSize);
	} else {
		HashtableOfObject cachedTable = (HashtableOfObject) this.categoryTables.get(categoryName);
		if (cachedTable != null)
			return cachedTable;
	}

	DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(getIndexFile()), 2048));
	HashtableOfObject categoryTable = null;
	char[][] matchingWords = null;
	int count = 0;
	int firstOffset = -1;
	try {
		stream.skip(offset);
		int size = stream.readInt();
		categoryTable = new HashtableOfObject(size);
		if (cacheDocNumbers)
			matchingWords = new char[size][];
		for (int i = 0; i < size; i++) {
			char[] word = Util.readUTF(stream);
			int arrayOffset = stream.readInt();
			if (arrayOffset > 0) {
				if (matchingWords != null) {
					if (count == 0)
						firstOffset = arrayOffset;
					matchingWords[count++] = word;
				}
				categoryTable.put(word, new Integer(arrayOffset)); // offset to array in the file
			} else {
				categoryTable.put(word, new int[] {-arrayOffset}); // stored a 1 element array by negating the documentNumber
			}
		}
		this.categoryTables.put(categoryName, categoryTable);
	} finally {
		stream.close();
	}

	if (count > 0) {
		stream = new DataInputStream(new BufferedInputStream(new FileInputStream(getIndexFile()), 2048));
		try {
			stream.skip(firstOffset);
			for (int i = 0; i < count; i++) // each array follows the previous one
				categoryTable.put(matchingWords[i], readDocumentArray(stream));
		} finally {
			stream.close();
		}
	}
	return categoryTable;
}
private void readChunk(String[] docNames, DataInputStream stream, int index, int size) throws IOException {
	String current = stream.readUTF();
	docNames[index++] = current;
	for (int i = 1; i < size; i++) {
		int start = stream.readUnsignedByte(); // number of identical characters at the beginning
		int end = stream.readUnsignedByte(); // number of identical characters at the end
		String next = stream.readUTF();
		if (start > 0) {
			if (end > 0) {
				int length = current.length();
				next = current.substring(0, start) + next + current.substring(length - end, length);
			} else {
				next = current.substring(0, start) + next;
			}
		} else if (end > 0) {
			int length = current.length();
			next = next + current.substring(length - end, length);
		}
		docNames[index++] = next;
		current = next;
	}
}
private int[] readDocumentArray(DataInputStream stream) throws IOException {
	int arraySize = stream.readShort();
	if (arraySize == 0x7FFF)
		arraySize = stream.readInt();
	int[] result = new int[arraySize];
	for (int i = 0; i < arraySize; i++) {
		switch (this.documentReferenceSize) {
			case 1 :
				result[i] = stream.readUnsignedByte();
				break;
			case 2 :
				result[i] = stream.readUnsignedShort();
				break;
			default :
				result[i] = stream.readInt();
				break;
		}
	}
	return result;
}
synchronized String readDocumentName(int docNumber) throws IOException {
	if (this.cachedChunks == null)
		this.cachedChunks = new String[this.numberOfChunks][];

	int chunkNumber = docNumber / CHUNK_SIZE;
	String[] chunk = this.cachedChunks[chunkNumber];
	if (chunk == null) {
		DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(getIndexFile()), 2048));
		try {
			stream.skip(this.chunkOffsets[chunkNumber]);
			int size = chunkNumber == this.numberOfChunks - 1 ? this.sizeOfLastChunk : CHUNK_SIZE;
			chunk = new String[size];
			readChunk(chunk, stream, 0, size);
		} finally {
			stream.close();
		}
		this.cachedChunks[chunkNumber] = chunk;
	}
	return chunk[docNumber - (chunkNumber * CHUNK_SIZE)];
}
synchronized int[] readDocumentNumbers(Object arrayOffset) throws IOException {
	// arrayOffset is either a cached array of docNumbers or an Integer offset in the file
	if (arrayOffset instanceof int[])
		return (int[]) arrayOffset;

	DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(getIndexFile()), 2048));
	try {
		stream.skip(((Integer) arrayOffset).intValue());
		return readDocumentArray(stream);
	} finally {
		stream.close();
	}
}
private void readHeaderInfo(RandomAccessFile file) throws IOException {
	file.seek(this.headerInfoOffset);

	// must be same order as writeHeaderInfo()
	this.numberOfChunks = file.readInt();
	this.sizeOfLastChunk = file.readUnsignedByte();
	this.documentReferenceSize = file.readUnsignedByte();

	this.chunkOffsets = new int[this.numberOfChunks];
	for (int i = 0; i < this.numberOfChunks; i++)
		this.chunkOffsets[i] = file.readInt();

	int size = file.readInt();
	this.categoryOffsets = new HashtableOfIntValues(size);
	for (int i = 0; i < size; i++)
		this.categoryOffsets.put(Util.readUTF(file), file.readInt()); // cache offset to category table
	this.categoryTables = new HashtableOfObject(size);
}
synchronized void startQuery() {
	this.cacheUserCount++;
}
synchronized void stopQuery() {
	if (--this.cacheUserCount < 0) {
		// clear cached items
		this.cacheUserCount = -1;
		this.cachedChunks = null;
		this.categoryTables = null;
	}
}
private void writeAllDocumentNames(String[] sortedDocNames, DataOutputStream stream) throws IOException {
	if (sortedDocNames.length == 0)
		throw new IllegalArgumentException();

	// assume the file was just created by initializeFrom()
	// in order, write: SIGNATURE & headerInfoOffset place holder, then each compressed chunk of document names
	stream.writeUTF(SIGNATURE);
	this.headerInfoOffset = stream.size();
	stream.writeInt(-1); // will overwrite with correct value later

	int size = sortedDocNames.length;
	this.numberOfChunks = (size / CHUNK_SIZE) + 1;
	this.sizeOfLastChunk = size % CHUNK_SIZE;
	if (this.sizeOfLastChunk == 0) {
		this.numberOfChunks--;
		this.sizeOfLastChunk = CHUNK_SIZE;
	}
	this.documentReferenceSize = size <= 0x7F ? 1 : (size <= 0x7FFF ? 2 : 4); // number of bytes used to encode a reference

	this.chunkOffsets = new int[this.numberOfChunks];
	int lastIndex = this.numberOfChunks - 1;
	for (int i = 0; i < this.numberOfChunks; i++) {
		this.chunkOffsets[i] = stream.size();

		int chunkSize = i == lastIndex ? this.sizeOfLastChunk : CHUNK_SIZE;
		int chunkIndex = i * CHUNK_SIZE;
		String current = sortedDocNames[chunkIndex];
		stream.writeUTF(current);
		for (int j = 1; j < chunkSize; j++) {
			String next = sortedDocNames[chunkIndex + j];
			int len1 = current.length();
			int len2 = next.length();
			int max = len1 < len2 ? len1 : len2;
			int start = 0; // number of identical characters at the beginning (also the index of first character that is different)
			while (current.charAt(start) == next.charAt(start)) {
				start++;
				if (max == start) break; // current is 'abba', next is 'abbab'
			}
			if (start > 255) start = 255;

			int end = 0; // number of identical characters at the end
			while (current.charAt(--len1) == next.charAt(--len2)) {
				end++;
				if (len2 == start) break; // current is 'abbba', next is 'abba'
			}
			if (end > 255) end = 255;
			stream.writeByte(start);
			stream.writeByte(end);

			int last = next.length() - end;
			stream.writeUTF(start < last ? next.substring(start, last) : ""); //$NON-NLS-1$
			current = next;
		}
	}
}
private void writeCategories(DataOutputStream stream) throws IOException {
	char[][] categoryNames = this.categoryTables.keyTable;
	Object[] tables = this.categoryTables.valueTable;
	for (int i = 0, l = categoryNames.length; i < l; i++)
		if (categoryNames[i] != null)
			writeCategoryTable(categoryNames[i], (HashtableOfObject) tables[i], stream);
	this.categoryTables = null;
}
private void writeCategoryTable(char[] categoryName, HashtableOfObject wordsToDocs, DataOutputStream stream) throws IOException {
	// append the file with the document number arrays & remember the offsets
	Object[] values = wordsToDocs.valueTable;
	for (int i = 0, l = values.length; i < l; i++) {
		Object o = values[i];
		if (o != null) {
			int[] documentNumbers = o instanceof int[] ? (int[]) o : ((IntList) o).asArray();
			int length = documentNumbers.length;
			if (length == 1) {
				values[i] = new Integer(-documentNumbers[0]); // store an array of 1 element by negating the documentNumber (can be zero)
			} else {
				values[i] = new Integer(stream.size());
				writeDocumentNumbers(documentNumbers, stream);
			}
		}
	}

	// append the file with the arrays followed by the words & offsets
	this.categoryOffsets.put(categoryName, stream.size()); // remember the offset to the start of the table
	this.categoryTables.put(categoryName, null); // flush cached table
	stream.writeInt(wordsToDocs.elementSize);
	char[][] words = wordsToDocs.keyTable;
	for (int i = 0, l = words.length; i < l; i++) {
		if (words[i] != null) {
			Util.writeUTF(stream, words[i]);
			stream.writeInt(((Integer) values[i]).intValue()); // offset in the file of the array of document numbers
		}
	}
}
private void writeDocumentNumbers(int[] documentNumbers, DataOutputStream stream) throws IOException {
	int length = documentNumbers.length;
	if (length < 0x7FFF) {
		if (length == 0)
			throw new IllegalArgumentException();
		stream.writeShort(length);
	} else {
		stream.writeShort(0x7FFF);
		stream.writeInt(length);
	}
	Util.sort(documentNumbers);
	for (int i = 0; i < length; i++) {
		switch (this.documentReferenceSize) {
			case 1 :
				stream.writeByte(documentNumbers[i]);
				break;
			case 2 :
				stream.writeShort(documentNumbers[i]);
				break;
			default :
				stream.writeInt(documentNumbers[i]);
				break;
		}
	}
}
private void writeHeaderInfo(DataOutputStream stream) throws IOException {
	stream.writeInt(this.numberOfChunks);
	stream.writeByte(this.sizeOfLastChunk);
	stream.writeByte(this.documentReferenceSize);

	// apend the file with chunk offsets
	for (int i = 0; i < this.numberOfChunks; i++)
		stream.writeInt(this.chunkOffsets[i]);

	// append the file with the category offsets... # of name -> offset pairs, followed by each name & an offset to its word->doc# table
	stream.writeInt(this.categoryOffsets.elementSize);
	char[][] categoryNames = this.categoryOffsets.keyTable;
	int[] offsets = this.categoryOffsets.valueTable;
	for (int i = 0, l = categoryNames.length; i < l; i++) {
		if (categoryNames[i] != null) {
			Util.writeUTF(stream, categoryNames[i]);
			stream.writeInt(offsets[i]);
		}
	}
}
private void writeOffsetToHeader(int offsetToHeader) throws IOException {
	if (offsetToHeader > 0) {
		RandomAccessFile file = new RandomAccessFile(this.fileName, "rw"); //$NON-NLS-1$
		try {
			file.seek(this.headerInfoOffset); // offset to position in header
			file.writeInt(offsetToHeader);
			this.headerInfoOffset = offsetToHeader; // update to reflect the correct offset
		} finally {
			file.close();
		}
	}
}
}