Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GROOVY-6928: Support all the Java 6 classes at createSimilarCollection() and createSimilarMap() #478

Merged
merged 1 commit into from
Mar 12, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 92 additions & 23 deletions src/main/org/codehaus/groovy/runtime/DefaultGroovyMethodsSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.*;
import java.util.concurrent.*;
import java.util.logging.Logger;

/**
Expand Down Expand Up @@ -154,7 +155,7 @@ protected static <T> Collection<T> createSimilarCollection(Collection<T> orig, i
return createSimilarList((List<T>) orig, newCapacity);
}
if (orig instanceof Queue) {
return new LinkedList<T>();
return createSimilarQueue((Queue<T>) orig);
}
return new ArrayList<T>(newCapacity);
}
Expand All @@ -169,6 +170,9 @@ protected static <T> List<T> createSimilarList(List<T> orig, int newCapacity) {
if (orig instanceof Vector)
return new Vector<T>();

if (orig instanceof CopyOnWriteArrayList)
return new CopyOnWriteArrayList<T>();

return new ArrayList<T>(newCapacity);
}

Expand All @@ -181,23 +185,75 @@ protected static <T> T[] createSimilarArray(T[] orig, int newCapacity) {
@SuppressWarnings("unchecked")
protected static <T> Set<T> createSimilarSet(Set<T> orig) {
if (orig instanceof SortedSet) {
return new TreeSet<T>(((SortedSet)orig).comparator());
Comparator comparator = ((SortedSet) orig).comparator();
if (orig instanceof ConcurrentSkipListSet) {
return new ConcurrentSkipListSet<T>(comparator);
} else {
return new TreeSet<T>(comparator);
}
} else {
if (orig instanceof CopyOnWriteArraySet) {
return new CopyOnWriteArraySet<T>();
} else {
// Do not use HashSet
return new LinkedHashSet<T>();
}
}
}

@SuppressWarnings("unchecked")
protected static <T> Queue<T> createSimilarQueue(Queue<T> orig) {
if (orig instanceof ArrayBlockingQueue) {
ArrayBlockingQueue queue = (ArrayBlockingQueue) orig;
return new ArrayBlockingQueue<T>(queue.size() + queue.remainingCapacity());
} else if (orig instanceof ArrayDeque) {
return new ArrayDeque<T>();
} else if (orig instanceof ConcurrentLinkedQueue) {
return new ConcurrentLinkedQueue<T>();
} else if (orig instanceof DelayQueue) {
return new DelayQueue();
} else if (orig instanceof LinkedBlockingDeque) {
return new LinkedBlockingDeque<T>();
} else if (orig instanceof LinkedBlockingQueue) {
return new LinkedBlockingQueue<T>();
} else if (orig instanceof PriorityBlockingQueue) {
return new PriorityBlockingQueue<T>();
} else if (orig instanceof PriorityQueue) {
return new PriorityQueue<T>(11, ((PriorityQueue) orig).comparator());
} else if (orig instanceof SynchronousQueue) {
return new SynchronousQueue<T>();
} else {
return new LinkedList<T>();
}
return new LinkedHashSet<T>();
}

@SuppressWarnings("unchecked")
protected static <K, V> Map<K, V> createSimilarMap(Map<K, V> orig) {
if (orig instanceof SortedMap) {
return new TreeMap<K, V>(((SortedMap)orig).comparator());
}
if (orig instanceof Properties) {
return (Map<K, V>) new Properties();
}
if (orig instanceof Hashtable) {
return new Hashtable<K, V>();
Comparator comparator = ((SortedMap) orig).comparator();
if (orig instanceof ConcurrentSkipListMap) {
return new ConcurrentSkipListMap<K, V>(comparator);
} else {
return new TreeMap<K, V>(comparator);
}
} else {
if (orig instanceof ConcurrentHashMap) {
return new ConcurrentHashMap<K, V>();
} else if (orig instanceof Hashtable) {
if (orig instanceof Properties) {
return (Map<K, V>) new Properties();
} else {
return new Hashtable<K, V>();
}
} else if (orig instanceof IdentityHashMap) {
return new IdentityHashMap<K, V>();
} else if (orig instanceof WeakHashMap) {
return new WeakHashMap<K, V>();
} else {
// Do not use HashMap
return new LinkedHashMap<K, V>();
}
}
return new LinkedHashMap<K, V>();
}

@SuppressWarnings("unchecked")
Expand All @@ -206,19 +262,32 @@ protected static <K, V> Map<K, V> createSimilarMap(Map<K, V> orig) {
if (answer != null) return answer;

// fall back to some defaults
if (orig instanceof TreeMap)
return new TreeMap<K, V>(orig);

if (orig instanceof Properties) {
Map<K, V> map = (Map<K, V>) new Properties();
map.putAll(orig);
return map;
if (orig instanceof SortedMap) {
if (orig instanceof ConcurrentSkipListMap) {
return new ConcurrentSkipListMap<K, V>(orig);
} else {
return new TreeMap<K, V>(orig);
}
} else {
if (orig instanceof ConcurrentHashMap) {
return new ConcurrentHashMap<K, V>(orig);
} else if (orig instanceof Hashtable) {
if (orig instanceof Properties) {
Map<K, V> map = (Map<K, V>) new Properties();
map.putAll(orig);
return map;
} else {
return new Hashtable<K, V>(orig);
}
} else if (orig instanceof IdentityHashMap) {
return new IdentityHashMap<K, V>(orig);
} else if (orig instanceof WeakHashMap) {
return new WeakHashMap<K, V>(orig);
} else {
// Do not use HashMap
return new LinkedHashMap<K, V>(orig);
}
}

if (orig instanceof Hashtable)
return new Hashtable<K, V>(orig);

return new LinkedHashMap<K, V>(orig);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* Copyright 2003-2014 the original author or authors.
*
* Licensed 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.codehaus.groovy.runtime

import java.util.concurrent.*

import static org.codehaus.groovy.runtime.DefaultGroovyMethodsSupport.createSimilarCollection
import static org.codehaus.groovy.runtime.DefaultGroovyMethodsSupport.createSimilarMap

/**
* @author Yu Kobayashi
*/
class DefaultGroovyMethodsSupportTest extends GroovyTestCase {
void testCreateSimilarCollectionForSets() {
def comparator = [
compare: { a, b -> b <=> a },
equals : { a, b -> a == b },
] as Comparator

Set set1 = new ConcurrentSkipListSet(comparator)
Set set2 = createSimilarCollection(set1)
set2 << 1 << 2 << 3
assert set2 instanceof ConcurrentSkipListSet
assert 3 == set2.head()
assert 1 == set2.last()

set1 = new TreeSet(comparator)
set2 = createSimilarCollection(set1)
set2 << 1 << 2 << 3
assert set2 instanceof TreeSet
assert 3 == set2.head()
assert 1 == set2.last()

set1 = new CopyOnWriteArraySet()
set2 = createSimilarCollection(set1)
set2 << 1 << 2 << 3
assert set2 instanceof CopyOnWriteArraySet
assert 1 in set2
assert 3 in set2

set1 = new LinkedHashSet()
set2 = createSimilarCollection(set1)
set2 << 1 << 2 << 3
assert set2 instanceof LinkedHashSet
assert 1 == set2.head()
assert 3 == set2.last()

set1 = new HashSet()
set2 = createSimilarCollection(set1)
set2 << 1 << 2 << 3
assert set2 instanceof LinkedHashSet // Not HashSet
assert 1 == set2.head()
assert 3 == set2.last()
}

void testCreateSimilarCollectionForLists() {
[
CopyOnWriteArrayList.class,
LinkedList.class,
Stack.class,
Vector.class,
ArrayList.class,
].each { testCase ->
List list = createSimilarCollection(testCase.newInstance() as Collection)
list << 1 << 2 << 3
assert testCase.is(list.getClass())
assert 1 == list.head()
assert 3 == list.last()
}
}

void testCreateSimilarCollectionForQueues() {
[
LinkedBlockingDeque.class,
LinkedList.class,
ArrayDeque.class,
ArrayBlockingQueue.class,
ConcurrentLinkedQueue.class,
DelayQueue.class,
LinkedBlockingQueue.class,
PriorityBlockingQueue.class,
PriorityQueue.class,
SynchronousQueue.class,
].each { testCase ->
Queue queue
if (testCase == ArrayBlockingQueue.class) {
queue = createSimilarCollection(new ArrayBlockingQueue(11))
} else if (testCase == PriorityQueue.class) {
def comparator = [
compare: { a, b -> b <=> a },
equals : { a, b -> a == b },
] as Comparator
queue = createSimilarCollection(new PriorityQueue(13, comparator))
assert comparator == ((PriorityQueue) queue).comparator()
} else {
queue = createSimilarCollection(testCase.newInstance() as Collection)
}

assert testCase == queue.getClass()

if (queue instanceof PriorityQueue) {
queue << 1 << 2 << 3
assert 3 == queue.head()
} else if (queue instanceof DelayQueue) {
[1, 2, 3].each { int i ->
queue << ([
getDelay : { TimeUnit unit -> i as long },
compareTo: { Delayed o -> i <=> o.getDelay(null) },
] as Delayed)
}
assert 1 == (queue.head() as Delayed).getDelay(null)
assert 3 == (queue.last() as Delayed).getDelay(null)
} else if (queue instanceof SynchronousQueue) {
// Do not do a add test
} else {
queue << 1 << 2 << 3
assert 1 == queue.head()
assert 3 == queue.last()
}
}
}

void testCreateSimilarMap() {
def comparator = [
compare: { a, b -> b <=> a },
equals : { a, b -> a == b },
] as Comparator
[
[ConcurrentSkipListMap.class, new ConcurrentSkipListMap(comparator)],
[TreeMap.class, new TreeMap(comparator)],
].each { testCase ->
Map map = createSimilarMap(testCase[1] as Map)
map[1] = 2
map[3] = 4
assert testCase[0] == map.getClass()
assert comparator == ((SortedMap) map).comparator()
assert 2 == map[1]
}

[
ConcurrentHashMap.class,
Properties.class,
Hashtable.class,
IdentityHashMap.class,
WeakHashMap.class,
LinkedHashMap.class,
HashMap.class,
].each { testCase ->
Map map = createSimilarMap(testCase.newInstance())
map[1] = 2
map[3] = 4
assert testCase == map.getClass() || (HashMap.class == testCase && LinkedHashMap.class == map.getClass())
assert 2 == map[1]
}
}
}