diff --git a/vtm/src/org/oscim/utils/KeyMap.java b/vtm/src/org/oscim/utils/KeyMap.java
new file mode 100644
index 00000000..7ece7e86
--- /dev/null
+++ b/vtm/src/org/oscim/utils/KeyMap.java
@@ -0,0 +1,641 @@
+package org.oscim.utils;
+
+/*
+ * Copyright 2014 Hannes Janetzek
+ *
+ * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Stripped down HashMap making HashItem entries public - So you have your custom
+ * 'Entry' holding key and value. HashItem must implement equals() and hashCode() 
+ * only for the 'key' part.
+ * 
+ * KeyMap.put(HashItem, boolean replace) allows to get or add an item in one invocation.
+ * 
+ * TODO add to NOTICE file
+ * The VTM library includes software developed as part of the Apache
+ * Harmony project which is copyright 2006, The Apache Software Foundation and
+ * released under the Apache License 2.0. http://harmony.apache.org
+ */
+/*
+ *  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.
+ */
+
+import java.util.Arrays;
+
+import org.oscim.utils.KeyMap.HashItem;
+import org.oscim.utils.pool.Inlist;
+
+/**
+ * <p>
+ * Note: the implementation of {@code KeyMap} is not synchronized. If one thread
+ * of several threads accessing an instance modifies the map structurally,
+ * access to the map needs to be synchronized. A structural modification is an
+ * operation that adds or removes an entry. Changes in the value of an entry are
+ * not structural changes.
+ * 
+ * @param <K> the type of keys maintained by this map
+ */
+public class KeyMap<K extends HashItem> {
+	/**
+	 * Min capacity (other than zero) for a HashMap. Must be a power of two
+	 * greater than 1 (and less than 1 << 30).
+	 */
+	private static final int MINIMUM_CAPACITY = 4;
+
+	/**
+	 * Max capacity for a HashMap. Must be a power of two >= MINIMUM_CAPACITY.
+	 */
+	private static final int MAXIMUM_CAPACITY = 1 << 30;
+
+	/**
+	 * An empty table shared by all zero-capacity maps (typically from default
+	 * constructor). It is never written to, and replaced on first put. Its size
+	 * is set to half the minimum, so that the first resize will create a
+	 * minimum-sized table.
+	 */
+	private static final HashItem[] EMPTY_TABLE = new HashItem[MINIMUM_CAPACITY >>> 1];
+
+	/**
+	 * The default load factor. Note that this implementation ignores the
+	 * load factor, but cannot do away with it entirely because it's
+	 * mentioned in the API.
+	 * 
+	 * <p>
+	 * Note that this constant has no impact on the behavior of the program, but
+	 * it is emitted as part of the serialized form. The load factor of .75 is
+	 * hardwired into the program, which uses cheap shifts in place of expensive
+	 * division.
+	 */
+	static final float DEFAULT_LOAD_FACTOR = .75F;
+
+	/**
+	 * The hash table. If this hash map contains a mapping for null, it is
+	 * not represented this hash table.
+	 */
+	HashItem[] table;
+
+	/**
+	 * The number of mappings in this hash map.
+	 */
+	int size;
+
+	/**
+	 * The table is rehashed when its size exceeds this threshold.
+	 * The value of this field is generally .75 * capacity, except when
+	 * the capacity is zero, as described in the EMPTY_TABLE declaration
+	 * above.
+	 */
+	private int threshold;
+
+	/**
+	 * Constructs a new empty {@code HashMap} instance.
+	 */
+	public KeyMap() {
+		table = (HashItem[]) EMPTY_TABLE;
+		threshold = -1; // Forces first put invocation to replace EMPTY_TABLE
+	}
+
+	/**
+	 * Constructs a new {@code HashMap} instance with the specified capacity.
+	 * 
+	 * @param capacity
+	 *            the initial capacity of this hash map.
+	 * @throws IllegalArgumentException
+	 *             when the capacity is less than zero.
+	 */
+	public KeyMap(int capacity) {
+		if (capacity < 0) {
+			throw new IllegalArgumentException("Capacity: " + capacity);
+		}
+
+		if (capacity == 0) {
+			HashItem[] tab = (HashItem[]) EMPTY_TABLE;
+			table = tab;
+			threshold = -1; // Forces first put() to replace EMPTY_TABLE
+			return;
+		}
+
+		if (capacity < MINIMUM_CAPACITY) {
+			capacity = MINIMUM_CAPACITY;
+		} else if (capacity > MAXIMUM_CAPACITY) {
+			capacity = MAXIMUM_CAPACITY;
+		} else {
+			capacity = roundUpToPowerOfTwo(capacity);
+		}
+		makeTable(capacity);
+	}
+
+	/**
+	 * Constructs a new {@code HashMap} instance with the specified capacity and
+	 * load factor.
+	 * 
+	 * @param capacity
+	 *            the initial capacity of this hash map.
+	 * @param loadFactor
+	 *            the initial load factor.
+	 * @throws IllegalArgumentException
+	 *             when the capacity is less than zero or the load factor is
+	 *             less or equal to zero or NaN.
+	 */
+	public KeyMap(int capacity, float loadFactor) {
+		this(capacity);
+
+		if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
+			throw new IllegalArgumentException("Load factor: " + loadFactor);
+		}
+
+		/* Note that this implementation ignores loadFactor; it always uses
+		 * a load factor of 3/4. This simplifies the code and generally
+		 * improves performance. */
+	}
+
+	/**
+	 * Returns an appropriate capacity for the specified initial size. Does
+	 * not round the result up to a power of two; the caller must do this!
+	 * The returned value will be between 0 and MAXIMUM_CAPACITY (inclusive).
+	 */
+	static int capacityForInitSize(int size) {
+		int result = (size >> 1) + size; // Multiply by 3/2 to allow for growth
+
+		// boolean expr is equivalent to result >= 0 && result<MAXIMUM_CAPACITY
+		return (result & ~(MAXIMUM_CAPACITY - 1)) == 0 ? result : MAXIMUM_CAPACITY;
+	}
+
+	/**
+	 * This method is called from the pseudo-constructors (clone and readObject)
+	 * prior to invoking constructorPut/constructorPutAll, which invoke the
+	 * overridden constructorNewEntry method. Normally it is a VERY bad idea to
+	 * invoke an overridden method from a pseudo-constructor (Effective Java
+	 * Item 17). In this case it is unavoidable, and the init method provides a
+	 * workaround.
+	 */
+	void init() {
+	}
+
+	/**
+	 * Returns whether this map is empty.
+	 * 
+	 * @return {@code true} if this map has no elements, {@code false}
+	 *         otherwise.
+	 * @see #size()
+	 */
+	public boolean isEmpty() {
+		return size == 0;
+	}
+
+	/**
+	 * Returns the number of elements in this map.
+	 * 
+	 * @return the number of elements in this map.
+	 */
+	public int size() {
+		return size;
+	}
+
+	/**
+	 * Returns the value of the mapping with the specified key.
+	 * 
+	 * @param key
+	 *            the key.
+	 * @return the value of the mapping with the specified key, or {@code null}
+	 *         if no mapping for the specified key is found.
+	 */
+	@SuppressWarnings("unchecked")
+	public K get(HashItem key) {
+		//		if (key == null) {
+		//			HashItem e = entryForNullKey;
+		//			return e == null ? null : e.key;
+		//		}
+
+		// Doug Lea's supplemental secondaryHash function (inlined)
+		int hash = key.hashCode();
+		hash ^= (hash >>> 20) ^ (hash >>> 12);
+		hash ^= (hash >>> 7) ^ (hash >>> 4);
+
+		HashItem[] tab = table;
+		for (HashItem e = tab[hash & (tab.length - 1)]; e != null; e = e.next) {
+			HashItem eKey = e;
+			if (eKey == key || (e.hash == hash && key.equals(eKey))) {
+				return (K) e;
+			}
+		}
+		return null;
+	}
+
+	//	/**
+	//	 * Returns whether this map contains the specified key.
+	//	 * 
+	//	 * @param key
+	//	 *            the key to search for.
+	//	 * @return {@code true} if this map contains the specified key,
+	//	 *         {@code false} otherwise.
+	//	 */
+	//	//@Override
+	//	public boolean containsKey(Object key) {
+	//		if (key == null) {
+	//			return entryForNullKey != null;
+	//		}
+	//
+	//		// Doug Lea's supplemental secondaryHash function (inlined)
+	//		int hash = key.hashCode();
+	//		hash ^= (hash >>> 20) ^ (hash >>> 12);
+	//		hash ^= (hash >>> 7) ^ (hash >>> 4);
+	//
+	//		HashItem[] tab = table;
+	//		for (HashItem e = tab[hash & (tab.length - 1)]; e != null; e = e.next) {
+	//			K eKey = e.key;
+	//			if (eKey == key || (e.hash == hash && key.equals(eKey))) {
+	//				return true;
+	//			}
+	//		}
+	//		return false;
+	//	}
+
+	//	/**
+	//	 * Returns whether this map contains the specified value.
+	//	 * 
+	//	 * @param value
+	//	 *            the value to search for.
+	//	 * @return {@code true} if this map contains the specified value,
+	//	 *         {@code false} otherwise.
+	//	 */
+	//	@Override
+	//	public boolean containsValue(Object value) {
+	//		HashMapEntry[] tab = table;
+	//		int len = tab.length;
+	//		if (value == null) {
+	//			for (int i = 0; i < len; i++) {
+	//				for (HashMapEntry e = tab[i]; e != null; e = e.next) {
+	//					if (e.value == null) {
+	//						return true;
+	//					}
+	//				}
+	//			}
+	//			return entryForNullKey != null && entryForNullKey.value == null;
+	//		}
+	//
+	//		// value is non-null
+	//		for (int i = 0; i < len; i++) {
+	//			for (HashMapEntry e = tab[i]; e != null; e = e.next) {
+	//				if (value.equals(e.value)) {
+	//					return true;
+	//				}
+	//			}
+	//		}
+	//		return entryForNullKey != null && value.equals(entryForNullKey.value);
+	//	}
+
+	/**
+	 * Maps the specified key to the specified value.
+	 * 
+	 * @param key
+	 *            the key.
+	 * @param value
+	 *            the value.
+	 * @return the value of any previous mapping with the specified key or
+	 *         {@code null} if there was no such mapping.
+	 */
+	public K put(K key) {
+		return put(key, true);
+	}
+
+	@SuppressWarnings("unchecked")
+	public K put(K key, boolean replace) {
+
+		int hash = secondaryHash(key.hashCode());
+		HashItem[] tab = table;
+		int index = hash & (tab.length - 1);
+		for (HashItem e = tab[index]; e != null; e = e.next) {
+			if (e.hash == hash && key.equals(e)) {
+				if (replace) {
+					tab[index] = Inlist.remove(tab[index], e);
+					tab[index] = Inlist.push(tab[index], key);
+				}
+				//V oldValue = e.value;
+				//e.value = value;
+				return (K) e; //oldValue;
+			}
+		}
+
+		// No entry key is present; create one
+		if (size++ > threshold) {
+			tab = doubleCapacity();
+			index = hash & (tab.length - 1);
+		}
+		addNewEntry(key, hash, index);
+		return null;
+	}
+
+	//	public K put(K key) {
+	//		//		if (key == null) {
+	//		//			return putValueForNullKey(value);
+	//		//		}
+	//
+	//		int hash = secondaryHash(key.hashCode());
+	//		HashItem[] tab = table;
+	//		int index = hash & (tab.length - 1);
+	//		for (HashItem e = tab[index]; e != null; e = e.next) {
+	//			if (e.hash == hash && key.equals(e.key)) {
+	//				preModify(e);
+	//				//V oldValue = e.value;
+	//				//e.value = value;
+	//				return e.key; //oldValue;
+	//			}
+	//		}
+	//
+	//		// No entry for (non-null) key is present; create one
+	//		modCount++;
+	//		if (size++ > threshold) {
+	//			tab = doubleCapacity();
+	//			index = hash & (tab.length - 1);
+	//		}
+	//		addNewEntry(key, hash, index);
+	//		return null;
+	//	}
+
+	//	private V putValueForNullKey(V value) {
+	//		HashMapEntry<K> entry = entryForNullKey;
+	//		if (entry == null) {
+	//			addNewEntryForNullKey(value);
+	//			size++;
+	//			modCount++;
+	//			return null;
+	//		} else {
+	//			preModify(entry);
+	//			V oldValue = entry.value;
+	//			entry.value = value;
+	//			return oldValue;
+	//		}
+	//	}
+
+	/**
+	 * Creates a new entry for the given key, value, hash, and index and
+	 * inserts it into the hash table. This method is called by put
+	 * (and indirectly, putAll), and overridden by LinkedHashMap. The hash
+	 * must incorporate the secondary hash function.
+	 */
+	void addNewEntry(K key, int hash, int index) {
+		key.setIndex(hash, table[index]);
+		table[index] = key;
+	}
+
+	///**
+	// * Ensures that the hash table has sufficient capacity to store the
+	// * specified number of mappings, with room to grow. If not, it increases the
+	// * capacity as appropriate. Like doubleCapacity, this method moves existing
+	// * entries to new buckets as appropriate. Unlike doubleCapacity, this method
+	// * can grow the table by factors of 2^n for n > 1. Hopefully, a single call
+	// * to this method will be faster than multiple calls to doubleCapacity.
+	// * 
+	// * <p>
+	// * This method is called only by putAll.
+	// */
+	//private void ensureCapacity(int numMappings) {
+	//	int newCapacity = roundUpToPowerOfTwo(capacityForInitSize(numMappings));
+	//	HashItem[] oldTable = table;
+	//	int oldCapacity = oldTable.length;
+	//	if (newCapacity <= oldCapacity) {
+	//		return;
+	//	}
+	//	if (newCapacity == oldCapacity * 2) {
+	//		doubleCapacity();
+	//		return;
+	//	}
+	//
+	//	// We're growing by at least 4x, rehash in the obvious way
+	//	HashItem[] newTable = makeTable(newCapacity);
+	//	if (size != 0) {
+	//		int newMask = newCapacity - 1;
+	//		for (int i = 0; i < oldCapacity; i++) {
+	//			for (HashItem e = oldTable[i]; e != null;) {
+	//				HashItem oldNext = e.next;
+	//				int newIndex = e.hash & newMask;
+	//				HashItem newNext = newTable[newIndex];
+	//				newTable[newIndex] = e;
+	//				e.next = newNext;
+	//				e = oldNext;
+	//			}
+	//		}
+	//	}
+	//}
+
+	/**
+	 * Allocate a table of the given capacity and set the threshold accordingly.
+	 * 
+	 * @param newCapacity must be a power of two
+	 */
+	private HashItem[] makeTable(int newCapacity) {
+		HashItem[] newTable = (HashItem[]) new HashItem[newCapacity];
+		table = newTable;
+		threshold = (newCapacity >> 1) + (newCapacity >> 2); // 3/4 capacity
+		return newTable;
+	}
+
+	/**
+	 * Doubles the capacity of the hash table. Existing entries are placed in
+	 * the correct bucket on the enlarged table. If the current capacity is,
+	 * MAXIMUM_CAPACITY, this method is a no-op. Returns the table, which
+	 * will be new unless we were already at MAXIMUM_CAPACITY.
+	 */
+	private HashItem[] doubleCapacity() {
+		HashItem[] oldTable = table;
+		int oldCapacity = oldTable.length;
+		if (oldCapacity == MAXIMUM_CAPACITY) {
+			return oldTable;
+		}
+		int newCapacity = oldCapacity * 2;
+		HashItem[] newTable = makeTable(newCapacity);
+		if (size == 0) {
+			return newTable;
+		}
+
+		for (int j = 0; j < oldCapacity; j++) {
+			/* Rehash the bucket using the minimum number of field writes.
+			 * This is the most subtle and delicate code in the class. */
+			HashItem e = oldTable[j];
+			if (e == null) {
+				continue;
+			}
+			int highBit = e.hash & oldCapacity;
+			HashItem broken = null;
+			newTable[j | highBit] = e;
+			for (HashItem n = e.next; n != null; e = n, n = n.next) {
+				int nextHighBit = n.hash & oldCapacity;
+				if (nextHighBit != highBit) {
+					if (broken == null)
+						newTable[j | nextHighBit] = n;
+					else
+						broken.next = n;
+					broken = e;
+					highBit = nextHighBit;
+				}
+			}
+			if (broken != null)
+				broken.next = null;
+		}
+		return newTable;
+	}
+
+	//	/**
+	//	 * Removes the mapping with the specified key from this map.
+	//	 * 
+	//	 * @param key
+	//	 *            the key of the mapping to remove.
+	//	 * @return the value of the removed mapping or {@code null} if no mapping
+	//	 *         for the specified key was found.
+	//	 */
+	//	@Override
+	//	public V remove(Object key) {
+	//		if (key == null) {
+	//			return removeNullKey();
+	//		}
+	//		int hash = secondaryHash(key.hashCode());
+	//		HashMapEntry<K>[] tab = table;
+	//		int index = hash & (tab.length - 1);
+	//		for (HashMapEntry<K> e = tab[index], prev = null; e != null; prev = e, e = e.next) {
+	//			if (e.hash == hash && key.equals(e.key)) {
+	//				if (prev == null) {
+	//					tab[index] = e.next;
+	//				} else {
+	//					prev.next = e.next;
+	//				}
+	//				modCount++;
+	//				size--;
+	//				postRemove(e);
+	//				return e.value;
+	//			}
+	//		}
+	//		return null;
+	//	}
+
+	/**
+	 * Subclass overrides this method to unlink entry.
+	 */
+	void postRemove(HashItem e) {
+	}
+
+	/**
+	 * Removes all mappings from this hash map, leaving it empty.
+	 * 
+	 * @see #isEmpty
+	 * @see #size
+	 */
+	public void clear() {
+		if (size != 0) {
+			Arrays.fill(table, null);
+			size = 0;
+		}
+	}
+
+	static final boolean STATS = false;
+
+	@SuppressWarnings("unchecked")
+	public K releaseItems() {
+		if (size == 0)
+			return null;
+
+		int collisions = 0;
+		int max = 0;
+		int sum = 0;
+
+		HashItem items = null;
+		HashItem last;
+		for (int i = 0, n = table.length; i < n; i++) {
+			HashItem item = table[i];
+			if (item == null)
+				continue;
+			table[i] = null;
+			if (STATS) {
+				sum = 0;
+				last = item;
+				while (last != null) {
+					if (last.next == null)
+						break;
+
+					sum++;
+					last = last.next;
+				}
+				max = Math.max(max, sum);
+				collisions += sum;
+			} else {
+				last = Inlist.last(item);
+			}
+			last.next = items;
+			items = item;
+		}
+		if (STATS)
+			System.out.println("collisions: " + collisions + " " + max + " " + size);
+
+		Arrays.fill(table, null);
+		size = 0;
+
+		return (K) items;
+	}
+
+	public static class HashItem extends Inlist<HashItem> {
+		int hash;
+
+		public void setIndex(int hash, HashItem next) {
+			this.hash = hash;
+			this.next = next;
+		}
+	}
+
+	/**
+	 * Applies a supplemental hash function to a given hashCode, which defends
+	 * against poor quality hash functions. This is critical because HashMap
+	 * uses power-of-two length hash tables, that otherwise encounter collisions
+	 * for hashCodes that do not differ in lower or upper bits.
+	 */
+	private static int secondaryHash(int h) {
+		// Doug Lea's supplemental hash function
+		h ^= (h >>> 20) ^ (h >>> 12);
+		return h ^ (h >>> 7) ^ (h >>> 4);
+	}
+
+	/**
+	 * Returns the smallest power of two >= its argument, with several caveats:
+	 * If the argument is negative but not Integer.MIN_VALUE, the method returns
+	 * zero. If the argument is > 2^30 or equal to Integer.MIN_VALUE, the method
+	 * returns Integer.MIN_VALUE. If the argument is zero, the method returns
+	 * zero.
+	 */
+	private static int roundUpToPowerOfTwo(int i) {
+		i--; // If input is a power of two, shift its high-order bit right
+
+		// "Smear" the high-order bit all the way to the right
+		i |= i >>> 1;
+		i |= i >>> 2;
+		i |= i >>> 4;
+		i |= i >>> 8;
+		i |= i >>> 16;
+
+		return i + 1;
+	}
+}