diff dwtx/core/internal/jobs/ObjectMap.d @ 122:9d0585bcb7aa

Add core.jobs package
author Frank Benoit <benoit@tionex.de>
date Tue, 12 Aug 2008 02:34:21 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/core/internal/jobs/ObjectMap.d	Tue Aug 12 02:34:21 2008 +0200
@@ -0,0 +1,354 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module dwtx.core.internal.jobs.ObjectMap;
+
+import dwt.dwthelper.utils;
+import dwtx.dwtxhelper.Collection;
+import dwtx.core.internal.jobs.StringPool;
+
+/**
+ * A specialized map implementation that is optimized for a small set of object
+ * keys.
+ *
+ * Implemented as a single array that alternates keys and values.
+ *
+ * Note: This class is copied from dwtx.core.resources
+ */
+public class ObjectMap : Map {
+    // 8 attribute keys, 8 attribute values
+    protected static const int DEFAULT_SIZE = 16;
+    protected static const int GROW_SIZE = 10;
+    protected int count = 0;
+    protected Object[] elements = null;
+
+    /**
+     * Creates a new object map.
+     *
+     * @param initialCapacity
+     *                  The initial number of elements that will fit in the map.
+     */
+    public this(int initialCapacity) {
+        if (initialCapacity > 0)
+            elements = new Object[Math.max(initialCapacity * 2, 0)];
+    }
+
+    /**
+     * Creates a new object map of the same size as the given map and populate
+     * it with the key/attribute pairs found in the map.
+     *
+     * @param map
+     *                  The entries in the given map will be added to the new map.
+     */
+    public this(Map map) {
+        this(map.size());
+        putAll(map);
+    }
+
+    /**
+     * @see Map#clear()
+     */
+    public void clear() {
+        elements = null;
+        count = 0;
+    }
+
+    /**
+     * @see java.lang.Object#clone()
+     */
+    public Object clone() {
+        return new ObjectMap(this);
+    }
+
+    /**
+     * @see Map#containsKey(java.lang.Object)
+     */
+    public bool containsKey(Object key) {
+        if (elements is null || count is 0)
+            return false;
+        for (int i = 0; i < elements.length; i = i + 2)
+            if (elements[i] !is null && elements[i].opEquals(key))
+                return true;
+        return false;
+    }
+    public bool containsKey(String key) {
+        return containsKey(stringcast(key));
+    }
+    /**
+     * @see Map#containsValue(java.lang.Object)
+     */
+    public bool containsValue(Object value) {
+        if (elements is null || count is 0)
+            return false;
+        for (int i = 1; i < elements.length; i = i + 2)
+            if (elements[i] !is null && elements[i].opEquals(value))
+                return true;
+        return false;
+    }
+
+    /**
+     * @see Map#entrySet()
+     *
+     * Note: This implementation does not conform properly to the
+     * specification in the Map interface. The returned collection will not
+     * be bound to this map and will not remain in sync with this map.
+     */
+    public Set entrySet() {
+        return count is 0 ? Collections.EMPTY_SET : toHashMap().entrySet();
+    }
+
+    /**
+     * @see Object#equals(java.lang.Object)
+     */
+    public override int opEquals(Object o) {
+        if (!(cast(Map)o ))
+            return false;
+        Map other = cast(Map) o;
+        //must be same size
+        if (count !is other.size())
+            return false;
+        //keysets must be equal
+        if (!(cast(Object)keySet()).opEquals(cast(Object)other.keySet()))
+            return false;
+        //values for each key must be equal
+        for (int i = 0; i < elements.length; i = i + 2) {
+            if (elements[i] !is null && (!elements[i + 1].opEquals(other.get(elements[i]))))
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * @see Map#get(java.lang.Object)
+     */
+    public Object get(Object key) {
+        if (elements is null || count is 0)
+            return null;
+        for (int i = 0; i < elements.length; i = i + 2)
+            if (elements[i] !is null && elements[i].opEquals(key))
+                return elements[i + 1];
+        return null;
+    }
+    public Object get(String key) {
+        return get(stringcast(key));
+    }
+
+    /**
+     * The capacity of the map has been exceeded, grow the array by GROW_SIZE to
+     * accomodate more entries.
+     */
+    protected void grow() {
+        Object[] expanded = new Object[elements.length + GROW_SIZE];
+        System.arraycopy(elements, 0, expanded, 0, elements.length);
+        elements = expanded;
+    }
+
+    /**
+     * @see Object#hashCode()
+     */
+    public override hash_t toHash() {
+        int hash = 0;
+        for (int i = 0; i < elements.length; i = i + 2) {
+            if (elements[i] !is null) {
+                hash += elements[i].toHash();
+            }
+        }
+        return hash;
+    }
+
+    /**
+     * @see Map#isEmpty()
+     */
+    public bool isEmpty() {
+        return count is 0;
+    }
+
+    /**
+     * Returns all keys in this table as an array.
+     */
+    public String[] keys() {
+        String[] result = new String[count];
+        int next = 0;
+        for (int i = 0; i < elements.length; i = i + 2)
+            if (elements[i] !is null)
+                result[next++] = stringcast( elements[i] );
+        return result;
+    }
+
+    /**
+     * @see Map#keySet()
+     *
+     * Note: This implementation does not conform properly to the
+     * specification in the Map interface. The returned collection will not
+     * be bound to this map and will not remain in sync with this map.
+     */
+    public Set keySet() {
+        Set result = new HashSet(size());
+        for (int i = 0; i < elements.length; i = i + 2) {
+            if (elements[i] !is null) {
+                result.add(elements[i]);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * @see Map#put(java.lang.Object, java.lang.Object)
+     */
+    public Object put(Object key, Object value) {
+        if (key is null)
+            throw new NullPointerException();
+        if (value is null)
+            return remove(key);
+
+        // handle the case where we don't have any attributes yet
+        if (elements is null)
+            elements = new Object[DEFAULT_SIZE];
+        if (count is 0) {
+            elements[0] = key;
+            elements[1] = value;
+            count++;
+            return null;
+        }
+
+        int emptyIndex = -1;
+        // replace existing value if it exists
+        for (int i = 0; i < elements.length; i += 2) {
+            if (elements[i] !is null) {
+                if (elements[i].opEquals(key)) {
+                    Object oldValue = elements[i + 1];
+                    elements[i + 1] = value;
+                    return oldValue;
+                }
+            } else if (emptyIndex is -1) {
+                // keep track of the first empty index
+                emptyIndex = i;
+            }
+        }
+        // this will put the emptyIndex greater than the size but
+        // that's ok because we will grow first.
+        if (emptyIndex is -1)
+            emptyIndex = count * 2;
+
+        // otherwise add it to the list of elements.
+        // grow if necessary
+        if (elements.length <= (count * 2))
+            grow();
+        elements[emptyIndex] = key;
+        elements[emptyIndex + 1] = value;
+        count++;
+        return null;
+    }
+    public Object put(String key, Object value) {
+        return put( stringcast(key), value );
+    }
+    public Object put(Object key, String value) {
+        return put( key, stringcast(value) );
+    }
+    public Object put(String key, String value) {
+        return put( stringcast(key), stringcast(value) );
+    }
+
+    /**
+     * @see Map#putAll(java.util.Map)
+     */
+    public void putAll(Map map) {
+        for (Iterator i = map.keySet().iterator(); i.hasNext();) {
+            Object key = i.next();
+            Object value = map.get(key);
+            put(key, value);
+        }
+    }
+
+    /**
+     * @see Map#remove(java.lang.Object)
+     */
+    public Object remove(Object key) {
+        if (elements is null || count is 0)
+            return null;
+        for (int i = 0; i < elements.length; i = i + 2) {
+            if (elements[i] !is null && elements[i].opEquals(key)) {
+                elements[i] = null;
+                Object result = elements[i + 1];
+                elements[i + 1] = null;
+                count--;
+                return result;
+            }
+        }
+        return null;
+    }
+    public Object remove(String key) {
+        return remove( stringcast(key));
+    }
+
+    /* (non-Javadoc
+     * Method declared on IStringPoolParticipant
+     */
+    public void shareStrings(StringPool set) {
+        //copy elements for thread safety
+        Object[] array = elements;
+        if (array is null)
+            return;
+        for (int i = 0; i < array.length; i++) {
+            Object o = array[i];
+            if (cast(ArrayWrapperString)o )
+                array[i] = stringcast(set.add(stringcast( o)));
+        }
+    }
+
+    /**
+     * @see Map#size()
+     */
+    public int size() {
+        return count;
+    }
+
+    /**
+     * Creates a new hash map with the same contents as this map.
+     */
+    private HashMap toHashMap() {
+        HashMap result = new HashMap(size());
+        for (int i = 0; i < elements.length; i = i + 2) {
+            if (elements[i] !is null) {
+                result.put(elements[i], elements[i + 1]);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * @see Map#values()
+     *
+     * Note: This implementation does not conform properly to the
+     * specification in the Map interface. The returned collection will not
+     * be bound to this map and will not remain in sync with this map.
+     */
+    public Collection values() {
+        Set result = new HashSet(size());
+        for (int i = 1; i < elements.length; i = i + 2) {
+            if (elements[i] !is null) {
+                result.add(elements[i]);
+            }
+        }
+        return result;
+    }
+
+    public int opApply (int delegate(ref Object value) dg){
+        implMissing(__FILE__, __LINE__ );
+        return 0;
+    }
+    public int opApply (int delegate(ref Object key, ref Object value) dg){
+        implMissing(__FILE__, __LINE__ );
+        return 0;
+    }
+
+}