git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@1040627 13f79535-47bb-0310-9956-ffa450edef68master
@@ -0,0 +1,130 @@ | |||
/* | |||
* 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. | |||
* | |||
*/ | |||
package org.apache.tools.ant.util; | |||
import java.util.Collection; | |||
import java.util.Enumeration; | |||
import java.util.Hashtable; | |||
import java.util.LinkedHashMap; | |||
import java.util.Map; | |||
import java.util.Set; | |||
/** | |||
* Subclass of Hashtable that wraps a LinkedHashMap to provide | |||
* predictable iteration order. | |||
* | |||
* <p>This is not a general purpose class but has been written because | |||
* the protected members of {@link org.apache.tools.ant.taskdefs.Copy | |||
* Copy} prohibited later revisions from using a more predictable | |||
* collection.</p> | |||
* | |||
* <p>Methods are synchronized to keep Hashtable's contract.</p> | |||
* | |||
* @since Ant 1.8.2 | |||
*/ | |||
public class LinkedHashtable extends Hashtable { | |||
private final LinkedHashMap map; | |||
public LinkedHashtable() { | |||
map = new LinkedHashMap(); | |||
} | |||
public LinkedHashtable(int initialCapacity) { | |||
map = new LinkedHashMap(initialCapacity); | |||
} | |||
public LinkedHashtable(int initialCapacity, float loadFactor) { | |||
map = new LinkedHashMap(initialCapacity, loadFactor); | |||
} | |||
public LinkedHashtable(Map m) { | |||
map = new LinkedHashMap(m); | |||
} | |||
public synchronized void clear() { | |||
map.clear(); | |||
} | |||
public boolean contains(Object value) { | |||
return containsKey(value); | |||
} | |||
public synchronized boolean containsKey(Object value) { | |||
return map.containsKey(value); | |||
} | |||
public synchronized boolean containsValue(Object value) { | |||
return map.containsValue(value); | |||
} | |||
public Enumeration elements() { | |||
return CollectionUtils.asEnumeration(values().iterator()); | |||
} | |||
public synchronized Set entrySet() { | |||
return map.entrySet(); | |||
} | |||
public synchronized boolean equals(Object o) { | |||
return map.equals(o); | |||
} | |||
public synchronized Object get(Object k) { | |||
return map.get(k); | |||
} | |||
public synchronized int hashCode() { | |||
return map.hashCode(); | |||
} | |||
public synchronized boolean isEmpty() { | |||
return map.isEmpty(); | |||
} | |||
public Enumeration keys() { | |||
return CollectionUtils.asEnumeration(keySet().iterator()); | |||
} | |||
public synchronized Set keySet() { | |||
return map.keySet(); | |||
} | |||
public synchronized Object put(Object k, Object v) { | |||
return map.put(k, v); | |||
} | |||
public synchronized void putAll(Map m) { | |||
map.putAll(m); | |||
} | |||
public synchronized Object remove(Object k) { | |||
return map.remove(k); | |||
} | |||
public synchronized int size() { | |||
return map.size(); | |||
} | |||
public synchronized String toString() { | |||
return map.toString(); | |||
} | |||
public synchronized Collection values() { | |||
return map.values(); | |||
} | |||
} |
@@ -0,0 +1,146 @@ | |||
/* | |||
* 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. | |||
* | |||
*/ | |||
package org.apache.tools.ant.util; | |||
import java.util.Hashtable; | |||
import java.util.Iterator; | |||
import java.util.Map; | |||
import junit.framework.TestCase; | |||
public class LinkedHashtableTest extends TestCase { | |||
private static final Object K1 = new Object(); | |||
private static final Object K2 = new Object(); | |||
private static final Object V1 = new Object(); | |||
private static final Object V2 = new Object(); | |||
private Hashtable h = new LinkedHashtable(); | |||
public void testClear() { | |||
h.put(K1, V1); | |||
h.clear(); | |||
assertTrue(h.isEmpty()); | |||
} | |||
public void testClone() { | |||
h.put(K1, V1); | |||
Hashtable h2 = (Hashtable) h.clone(); | |||
assertTrue(h2 instanceof LinkedHashtable); | |||
assertTrue(h2.containsKey(K1)); | |||
} | |||
public void testContainsAndPut() { | |||
h.put(K1, V1); | |||
assertTrue(h.contains(K1)); | |||
assertTrue(h.containsKey(K1)); | |||
assertTrue(h.containsValue(V1)); | |||
assertFalse(h.containsKey(K2)); | |||
} | |||
public void testGet() { | |||
assertNull(h.get(K1)); | |||
h.put(K1, V1); | |||
assertSame(V1, h.get(K1)); | |||
} | |||
public void testIsEmpty() { | |||
assertTrue(h.isEmpty()); | |||
h.put(K1, V1); | |||
assertFalse(h.isEmpty()); | |||
} | |||
public void testPutReturnValue() { | |||
assertNull(h.put(K1, V1)); | |||
assertSame(V1, h.put(K1, V2)); | |||
} | |||
public void testPutAll() { | |||
LinkedHashtable h2 = new LinkedHashtable(); | |||
h.put(K1, V1); | |||
h2.putAll(h); | |||
assertTrue(h2.containsKey(K1)); | |||
} | |||
public void testRemove() { | |||
h.put(K1, V1); | |||
assertSame(V1, h.remove(K1)); | |||
assertTrue(h.isEmpty()); | |||
assertNull(h.remove(K1)); | |||
} | |||
public void testSize() { | |||
assertEquals(0, h.size()); | |||
h.put(K1, V1); | |||
assertEquals(1, h.size()); | |||
} | |||
public void testKeys() { | |||
multiSetup(); | |||
assertKeys(CollectionUtils.asIterator(h.keys())); | |||
} | |||
public void testKeySet() { | |||
multiSetup(); | |||
assertKeys(h.keySet().iterator()); | |||
} | |||
public void testElements() { | |||
multiSetup(); | |||
assertValues(CollectionUtils.asIterator(h.elements())); | |||
} | |||
public void testValues() { | |||
multiSetup(); | |||
assertValues(h.values().iterator()); | |||
} | |||
public void testEntrySet() { | |||
multiSetup(); | |||
Iterator i = h.entrySet().iterator(); | |||
assertTrue(i.hasNext()); | |||
Map.Entry e = (Map.Entry) i.next(); | |||
assertSame(K1, e.getKey()); | |||
assertSame(V1, e.getValue()); | |||
assertTrue(i.hasNext()); | |||
e = (Map.Entry) i.next(); | |||
assertSame(K2, e.getKey()); | |||
assertSame(V2, e.getValue()); | |||
assertFalse(i.hasNext()); | |||
} | |||
private void multiSetup() { | |||
h.put(K1, V1); | |||
h.put(K2, V2); | |||
} | |||
private static void assertKeys(Iterator i) { | |||
assertTrue(i.hasNext()); | |||
assertSame(K1, i.next()); | |||
assertTrue(i.hasNext()); | |||
assertSame(K2, i.next()); | |||
assertFalse(i.hasNext()); | |||
} | |||
private static void assertValues(Iterator i) { | |||
assertTrue(i.hasNext()); | |||
assertSame(V1, i.next()); | |||
assertTrue(i.hasNext()); | |||
assertSame(V2, i.next()); | |||
assertFalse(i.hasNext()); | |||
} | |||
} |