/*******************************************************************************
 * Copyright (c) 2009 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.core.internal.registry;

/**
 * Essentially a map String -> String[] for small number of keys.
 *
 * For Maps containing a small number of objects hashing often reduces performance.
 * This implementation uses two parallel arrays, one for keys, one for
 * values, and grows them as necessary.
 */
public class DirectMap {

	final private float growthFactor;

	private String[] keyArray;
	private String[][] valueArray;
	private int size;

	public DirectMap(int initialSize, float growthFactor) {
		if (initialSize < 1)
			throw new IllegalArgumentException();
		if (growthFactor <= 0)
			throw new IllegalArgumentException();
		this.growthFactor = growthFactor;
		keyArray = new String[initialSize];
		valueArray = new String[initialSize][];
		size = 0;
	}

	public synchronized void put(String key, String[] value) {
		if (key == null)
			throw new IllegalArgumentException();
		int id = findKey(key);
		if (id != -1)
			throw new IllegalArgumentException();

		if (size >= keyArray.length) { // need to resize
			int newSize = recalcSize(keyArray.length);
			if (newSize <= size)
				newSize = size + 1;

			String[] newKeyArray = new String[newSize];
			System.arraycopy(keyArray, 0, newKeyArray, 0, keyArray.length);
			keyArray = newKeyArray;

			String[][] newValueArray = new String[newSize][];
			System.arraycopy(valueArray, 0, newValueArray, 0, valueArray.length);
			valueArray = newValueArray;
		}
		keyArray[size] = key;
		valueArray[size] = value;
		size++;
	}

	public synchronized boolean containsKey(String key) {
		if (key == null)
			throw new IllegalArgumentException();
		return (findKey(key) != -1);
	}

	public synchronized String[] get(String key) {
		if (key == null)
			throw new IllegalArgumentException();
		int id = findKey(key);
		if (id == -1)
			return null;
		return valueArray[id];
	}

	/* package */String[] getKeys() {
		return keyArray;
	}

	/* package */String[][] getValues() {
		return valueArray;
	}

	/* package */int getSzie() {
		return size;
	}

	private int recalcSize(int currentSize) {
		return (int) (currentSize * (1.0f + growthFactor));
	}

	private int findKey(String key) {
		for (int i = 0; i < keyArray.length; i++) {
			if (keyArray[i] == null)
				continue;
			if (keyArray[i].equals(key))
				return i;
		}
		return -1;
	}
}
