/**
* This file is part of OSM2ShareNav
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* Copyright (C) 2008 Kai Krueger
*
*/
package net.sharenav.osmToShareNav;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
*
* @param <K>
* @param <V>
*
*/
public class LongArrayMap<K extends Long, V> implements Map<Long, V> {
class LongArrayMapValueSet implements Set<V> {
/* (non-Javadoc)
* @see java.util.Set#add(java.lang.Object)
*/
private LongArrayMap<K,V> lam;
public LongArrayMapValueSet(LongArrayMap<K,V> lam) {
this.lam = lam;
}
@Override
public boolean add(Object e) {
throw new Error("Function ValueSet.add is not implemented yet");
}
/* (non-Javadoc)
* @see java.util.Set#addAll(java.util.Collection)
*/
@Override
public boolean addAll(Collection c) {
throw new Error("Function ValueSet.addAll is not implemented yet");
}
/* (non-Javadoc)
* @see java.util.Set#clear()
*/
@Override
public void clear() {
throw new Error("Function ValueSet.clear is not implemented yet");
}
/* (non-Javadoc)
* @see java.util.Set#contains(java.lang.Object)
*/
@Override
public boolean contains(Object o) {
throw new Error("Function ValueSet.contains is not implemented yet");
}
/* (non-Javadoc)
* @see java.util.Set#containsAll(java.util.Collection)
*/
@Override
public boolean containsAll(Collection c) {
throw new Error("Function ValueSet.containsAll is not implemented yet");
}
/* (non-Javadoc)
* @see java.util.Set#isEmpty()
*/
@Override
public boolean isEmpty() {
throw new Error("Function ValueSet.isEmpty is not implemented yet");
}
/* (non-Javadoc)
* @see java.util.Set#iterator()
*/
@Override
public Iterator<V> iterator() {
return new Iterator<V>() {
int entry = 0;
int element = -1;
@Override
public boolean hasNext() {
//try {
if ((lam.noEntries <= entry) ||
((lam.noEntries -1 == entry) && (lam.valueTree[entry].size <= element)) ||
(lam.noEntries <= (entry + 1)&&((lam.valueTree[entry].size <= element + 1))))
return false;
return true;
/*} catch (NullPointerException npe) {
System.out.println("entry " + entry + " element " + element + "noEntries " + noEntries);
return false;
}*/
}
@Override
public V next() {
element++;
//try {
if (lam.valueTree[entry].size <= element) {
entry++;
element = 0;
}
V o = (V)lam.valueTree[entry].values[element];
return o;
/*} catch (NullPointerException npe) {
System.out.println("entry " + entry + " element " + element + "noEntries " + noEntries);
return null;
}*/
}
@Override
public void remove() {
lam.remove(lam.valueTree[entry].keys[element]);
element--;
}
};
}
/* (non-Javadoc)
* @see java.util.Set#remove(java.lang.Object)
*/
@Override
public boolean remove(Object o) {
System.out.println("MapValueSet.remove");
return false;
}
/* (non-Javadoc)
* @see java.util.Set#removeAll(java.util.Collection)
*/
@Override
public boolean removeAll(Collection c) {
throw new Error("Function ValueSet.removeAll is not implemented yet");
}
/* (non-Javadoc)
* @see java.util.Set#retainAll(java.util.Collection)
*/
@Override
public boolean retainAll(Collection c) {
throw new Error("Function ValueSet.retainAll is not implemented yet");
}
/* (non-Javadoc)
* @see java.util.Set#size()
*/
@Override
public int size() {
return lam.size;
}
/* (non-Javadoc)
* @see java.util.Set#toArray()
*/
@Override
public Object[] toArray() {
throw new Error("Function ValueSet.toArray is not implemented yet");
}
/* (non-Javadoc)
* @see java.util.Set#toArray(T[])
*/
@Override
public V[] toArray(Object[] a) {
throw new Error("Function ValueSet.toArray2 is not implemented yet");
}
}
private class LongArrayMapEntry<V> {
long [] keys;
Object[] values;
long minKey, maxKey;
int size;
public LongArrayMapEntry(int capacity) {
keys = new long[capacity];
values = new Object[capacity];
for (int i = 0; i < keys.length; i++) {
keys[i] = Long.MIN_VALUE;
}
size = 0;
}
/**
*
* @param key
* @return index to where the key is stored. If the key is not part of the array, then return one plus the index of the next smallest key
*/
private int key2idx(long key) {
int minIdx = 0;
int maxIdx = size - 1;
if (size == 0)
return 0;
if (keys[maxIdx] < key) {
return maxIdx + 1;
}
int pivot = (minIdx + maxIdx)/2;
while (keys[minIdx] < key) {
pivot = (minIdx + maxIdx)/2;
//System.out.println("Entry.key2idx(" + key + ") = (" + minIdx + "|" + pivot + "|" + maxIdx + ")");
if (keys[pivot] == key)
return pivot;
if (keys[pivot] > key) {
maxIdx = pivot;
} else {
if (minIdx == pivot) {
minIdx++;
} else {
minIdx = pivot;
}
}
}
if (keys[pivot] == key)
return pivot;
if (keys[maxIdx] == key)
return maxIdx;
else pivot = minIdx;
//System.out.println("Entry.key2idx(" + key + ") = " + pivot + " size: " + size);
return pivot;
}
public boolean containsKey(long key) {
int idx = key2idx(key);
if ((keys[idx] == key) && values[idx] != null) {
return true;
}
return false;
}
public boolean containsValue(Object value) {
for (int i = 0; i < size; i++) {
if (values[i] == value)
return true;
}
return false;
}
public V get(long key) {
int idx = key2idx(key);
if ((keys[idx] == key)) {
return (V)values[idx];
}
return null;
}
public V put(long key, V value) {
int idx = key2idx(key);
if (values[idx] != null ) {
if (keys[idx] == key) {
//Replace value
V oldValue = (V)values[idx];
values[idx] = value;
return oldValue;
} else {
if (size == keys.length) {
System.out.println("Error: Inserting out of order too often!");
System.exit(1);
return null;
}
System.arraycopy(keys, idx, keys, idx + 1, size - idx);
System.arraycopy(values, idx, values, idx + 1, size - idx);
}
}
values[idx] = value;
keys[idx] = key;
size++;
return null;
}
public boolean isFull() {
return ((size + 10 + (keys.length/1000) )> keys.length);
}
private void remove(int elementIdx) {
System.arraycopy(keys, elementIdx + 1, keys, elementIdx, size - elementIdx);
System.arraycopy(values, elementIdx + 1, values, elementIdx, size - elementIdx);
size--;
}
private void remove(long elementKey) {
int idx = key2idx(elementKey);
if (keys[idx] == elementKey) {
remove(idx);
}
}
}
long [] keyIdx;
LongArrayMapEntry<V> [] valueTree;
int size;
int capPerEntry;
int noEntries;
public LongArrayMap(int capPerEntry) {
this.capPerEntry = capPerEntry;
clear();
}
private int key2idx(long key, boolean debug) {
int minIdx = 0;
int maxIdx = noEntries - 1;
int pivot = (minIdx + maxIdx)/2;
if (debug)
System.out.println("key2idx(" + key + ") = ? noEntires: " + noEntries);
if (noEntries == 0)
return -1;
if (keyIdx[maxIdx] < key) {
return maxIdx;
}
while (minIdx < maxIdx) {
//System.out.println("key2idx(" + key + ") = " + pivot + " minIdx " + minIdx + " maxIdx " + maxIdx);
if (keyIdx[minIdx] == key) {
//System.out.println("found it");
return minIdx;
}
if (keyIdx[maxIdx] == key) {
//System.out.println("found it");
return maxIdx;
}
pivot = (minIdx + maxIdx)/2;
if (keyIdx[pivot] > key) {
maxIdx = pivot;
} else {
if (minIdx == pivot) {
minIdx = pivot + 1;
} else {
minIdx = pivot;
}
}
}
pivot = (minIdx + maxIdx)/2;
if (debug) {
System.out.print("key2idx(" + key + ") = " + pivot + " maxIdx " + maxIdx + " noEntires: " + noEntries);
for (long i : keyIdx)
System.out.print(" " + i + " ");
System.out.println("");
}
return pivot;
}
/* (non-Javadoc)
* @see java.util.Map#clear()
*/
@Override
public void clear() {
keyIdx = new long[100];
valueTree = new LongArrayMapEntry[100];
for (int i = 0; i < keyIdx.length; i++) {
keyIdx[i] = Long.MAX_VALUE;
}
size = 0;
noEntries = 0;
}
/* (non-Javadoc)
* @see java.util.Map#containsKey(java.lang.Object)
*/
@Override
public boolean containsKey(Object key) {
long keyLong;
if (!(key instanceof Long))
return false;
keyLong = ((Long)key).longValue();
int idx = key2idx(keyLong, false);
if (idx < 0) return false;
return valueTree[idx].containsKey(keyLong);
}
/* (non-Javadoc)
* @see java.util.Map#containsValue(java.lang.Object)
*/
@Override
public boolean containsValue(Object value) {
for (LongArrayMapEntry<V> entry : valueTree) {
if (entry != null)
if (entry.containsValue(value))
return true;
}
return false;
}
/* (non-Javadoc)
* @see java.util.Map#entrySet()
*/
@Override
public Set<java.util.Map.Entry<Long, V>> entrySet() {
throw new Error("Function entrySet is not implemented yet");
}
/* (non-Javadoc)
* @see java.util.Map#get(java.lang.Object)
*/
@Override
public V get(Object key) {
long keyLong;
if (!(key instanceof Long))
return null;
keyLong = ((Long)key).longValue();
return get(keyLong);
}
public V get(long keyLong) {
int idx = key2idx(keyLong,false);
if (idx < 0)
return null;
if (keyIdx[idx] < keyLong) {
//System.out.println("Get key " + keyLong + " idx = " + idx + " " + keyIdx[idx]);
//key2idx(keyLong,true);
}
if (idx < 0)
return null;
return valueTree[idx].get(keyLong);
}
/* (non-Javadoc)
* @see java.util.Map#isEmpty()
*/
@Override
public boolean isEmpty() {
return (size == 0);
}
/* (non-Javadoc)
* @see java.util.Map#keySet()
*/
@Override
public Set<Long> keySet() {
throw new Error("Function keySet is not implemented yet");
}
/* (non-Javadoc)
* @see java.util.Map#put(java.lang.Object, java.lang.Object)
*/
@Override
public V put(Long key, V value) {
long keyLong;
if (!(key instanceof Long))
return null;
keyLong = ((Long)key).longValue();
int idx = key2idx(keyLong,false);
if (idx == -1) {
if (noEntries == 0) {
valueTree[0] = new LongArrayMapEntry<V>(capPerEntry);
noEntries++;
}
idx = noEntries - 1;
}
if (valueTree[idx].isFull()) {
if (valueTree[idx + 1] == null) {
//System.out.println("Is full");
valueTree[idx + 1] = new LongArrayMapEntry<V>(capPerEntry);
noEntries++;
idx++;
}
}
//System.out.println("Putting to idx " + idx);
valueTree[idx].put(keyLong,value);
if ((keyIdx[idx] <= keyLong) || (keyIdx[idx] == Long.MAX_VALUE)) {
keyIdx[idx] = keyLong;
}
size++;
//System.out.println("Key idx: " + keyIdx[idx]);
return null;
}
/* (non-Javadoc)
* @see java.util.Map#putAll(java.util.Map)
*/
@Override
public void putAll(Map<? extends Long, ? extends V> m) {
throw new Error("Function putAll is not implemented yet");
}
/* (non-Javadoc)
* @see java.util.Map#remove(java.lang.Object)
*/
@Override
public V remove(Object key) {
long keyLong;
if (!(key instanceof Long))
return null;
keyLong = ((Long)key).longValue();
int idx = key2idx(keyLong,false);
if (idx < 0)
return null;
V obj = valueTree[idx].get(keyLong);
if (obj != null) {
valueTree[idx].remove(keyLong);
size--;
}
return obj;
}
/* (non-Javadoc)
* @see java.util.Map#size()
*/
@Override
public int size() {
return size;
}
/* (non-Javadoc)
* @see java.util.Map#values()
*/
@Override
public Collection<V> values() {
return new LongArrayMapValueSet(this);
}
}