diff --git a/compat/src/main/scala-2.11/scala/jdk/javaapi/CollectionConverters.scala b/compat/src/main/scala-2.11/scala/jdk/javaapi/CollectionConverters.scala new file mode 100644 index 00000000..af0b911b --- /dev/null +++ b/compat/src/main/scala-2.11/scala/jdk/javaapi/CollectionConverters.scala @@ -0,0 +1,65 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala.jdk.javaapi + +import java.{lang => jl, util => ju}, java.util.{concurrent => juc} +import scala.collection.convert.{WrapAsJava, WrapAsScala} +import scala.collection._ + +/** This object contains methods that convert between Scala and Java collections. + * + * The explicit conversion methods defined here are intended to be used in Java code. For Scala + * code, it is recommended to use the extension methods defined in + * [[scala.jdk.CollectionConverters]]. + */ +object CollectionConverters extends WrapAsJava with WrapAsScala { + def asJava[A](i: Iterator[A]): ju.Iterator[A] = asJavaIterator(i) + + def asJava[A](i: Iterable[A]): jl.Iterable[A] = asJavaIterable(i) + + def asJava[A](b: mutable.Buffer[A]): ju.List[A] = bufferAsJavaList(b) + + def asJava[A](s: mutable.Seq[A]): ju.List[A] = mutableSeqAsJavaList(s) + + def asJava[A](s: Seq[A]): ju.List[A] = seqAsJavaList(s) + + def asJava[A](s: mutable.Set[A]): ju.Set[A] = mutableSetAsJavaSet(s) + + def asJava[A](s: Set[A]): ju.Set[A] = setAsJavaSet(s) + + def asJava[K, V](m: mutable.Map[K, V]): ju.Map[K, V] = mutableMapAsJavaMap(m) + + def asJava[K, V](m: Map[K, V]): ju.Map[K, V] = mapAsJavaMap(m) + + def asJava[K, V](m: concurrent.Map[K, V]): juc.ConcurrentMap[K, V] = mapAsJavaConcurrentMap(m) + + def asScala[A](i: ju.Iterator[A]): Iterator[A] = asScalaIterator(i) + + def asScala[A](e: ju.Enumeration[A]): Iterator[A] = enumerationAsScalaIterator(e) + + def asScala[A](i: jl.Iterable[A]): Iterable[A] = iterableAsScalaIterable(i) + + def asScala[A](c: ju.Collection[A]): Iterable[A] = collectionAsScalaIterable(c) + + def asScala[A](l: ju.List[A]): mutable.Buffer[A] = asScalaBuffer(l) + + def asScala[A](s: ju.Set[A]): mutable.Set[A] = asScalaSet(s) + + def asScala[A, B](m: ju.Map[A, B]): mutable.Map[A, B] = mapAsScalaMap(m) + + def asScala[A, B](m: juc.ConcurrentMap[A, B]): concurrent.Map[A, B] = mapAsScalaConcurrentMap(m) + + def asScala[A, B](d: ju.Dictionary[A, B]): mutable.Map[A, B] = dictionaryAsScalaMap(d) + + def asScala(p: ju.Properties): mutable.Map[String, String] = propertiesAsScalaMap(p) +} diff --git a/compat/src/main/scala-2.12/scala/jdk/javaapi/CollectionConverters.scala b/compat/src/main/scala-2.12/scala/jdk/javaapi/CollectionConverters.scala new file mode 100644 index 00000000..1266d8b2 --- /dev/null +++ b/compat/src/main/scala-2.12/scala/jdk/javaapi/CollectionConverters.scala @@ -0,0 +1,65 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala.jdk.javaapi + +import java.{lang => jl, util => ju}, java.util.{concurrent => juc} +import scala.collection.convert.{AsJavaConverters, AsScalaConverters} +import scala.collection._ + +/** This object contains methods that convert between Scala and Java collections. + * + * The explicit conversion methods defined here are intended to be used in Java code. For Scala + * code, it is recommended to use the extension methods defined in + * [[scala.jdk.CollectionConverters]]. + */ +object CollectionConverters extends AsJavaConverters with AsScalaConverters { + def asJava[A](i: Iterator[A]): ju.Iterator[A] = asJavaIterator(i) + + def asJava[A](i: Iterable[A]): jl.Iterable[A] = asJavaIterable(i) + + def asJava[A](b: mutable.Buffer[A]): ju.List[A] = bufferAsJavaList(b) + + def asJava[A](s: mutable.Seq[A]): ju.List[A] = mutableSeqAsJavaList(s) + + def asJava[A](s: Seq[A]): ju.List[A] = seqAsJavaList(s) + + def asJava[A](s: mutable.Set[A]): ju.Set[A] = mutableSetAsJavaSet(s) + + def asJava[A](s: Set[A]): ju.Set[A] = setAsJavaSet(s) + + def asJava[K, V](m: mutable.Map[K, V]): ju.Map[K, V] = mutableMapAsJavaMap(m) + + def asJava[K, V](m: Map[K, V]): ju.Map[K, V] = mapAsJavaMap(m) + + def asJava[K, V](m: concurrent.Map[K, V]): juc.ConcurrentMap[K, V] = mapAsJavaConcurrentMap(m) + + def asScala[A](i: ju.Iterator[A]): Iterator[A] = asScalaIterator(i) + + def asScala[A](e: ju.Enumeration[A]): Iterator[A] = enumerationAsScalaIterator(e) + + def asScala[A](i: jl.Iterable[A]): Iterable[A] = iterableAsScalaIterable(i) + + def asScala[A](c: ju.Collection[A]): Iterable[A] = collectionAsScalaIterable(c) + + def asScala[A](l: ju.List[A]): mutable.Buffer[A] = asScalaBuffer(l) + + def asScala[A](s: ju.Set[A]): mutable.Set[A] = asScalaSet(s) + + def asScala[A, B](m: ju.Map[A, B]): mutable.Map[A, B] = mapAsScalaMap(m) + + def asScala[A, B](m: juc.ConcurrentMap[A, B]): concurrent.Map[A, B] = mapAsScalaConcurrentMap(m) + + def asScala[A, B](d: ju.Dictionary[A, B]): mutable.Map[A, B] = dictionaryAsScalaMap(d) + + def asScala(p: ju.Properties): mutable.Map[String, String] = propertiesAsScalaMap(p) +} diff --git a/compat/src/test/scala-jvm/test/scala/jdk/javaapi/CollectionConvertersTest.java b/compat/src/test/scala-jvm/test/scala/jdk/javaapi/CollectionConvertersTest.java new file mode 100644 index 00000000..6567fe97 --- /dev/null +++ b/compat/src/test/scala-jvm/test/scala/jdk/javaapi/CollectionConvertersTest.java @@ -0,0 +1,128 @@ +package test.scala.jdk.javaapi; + +import org.junit.Assert; +import org.junit.Test; +import scala.Array; +import scala.Tuple2; +import scala.collection.Iterable; +import scala.collection.Iterator; +import scala.collection.concurrent.TrieMap; +import scala.collection.mutable.*; +import scala.collection.mutable.Map; +import scala.collection.mutable.Set; +import scala.jdk.javaapi.CollectionConverters; + +import java.util.*; +import java.util.concurrent.ConcurrentMap; + +public class CollectionConvertersTest { + + /** + * The following conversions are supported via asScala and asJava: + * + * scala.collection.Iterable <=> java.lang.Iterable + * scala.collection.Iterator <=> java.util.Iterator + * scala.collection.mutable.Buffer <=> java.util.List + * scala.collection.mutable.Set <=> java.util.Set + * scala.collection.mutable.Map <=> java.util.Map + * scala.collection.concurrent.Map <=> java.util.concurrent.ConcurrentMap + */ + @Test + public void shouldConvertAsScala() { + // scala.collection.Iterable <=> java.lang.Iterable + java.lang.Iterable iterable = CollectionConverters.asJava(TestObjects.iterable()); + Assert.assertEquals("A", iterable.iterator().next()); + Iterable scalaIterable = CollectionConverters.asScala(iterable); + Assert.assertEquals(TestObjects.iterable().head(), scalaIterable.head()); + + // scala.collection.Iterator <=> java.util.Iterator + java.util.Iterator iterator = CollectionConverters.asJava(TestObjects.iterator()); + Assert.assertEquals("A", iterator.next()); + Iterator scalaIterator = CollectionConverters.asScala(iterator); + Assert.assertTrue(scalaIterator.contains("B")); + + // scala.collection.mutable.Buffer <=> java.util.List + List list = CollectionConverters.asJava(TestObjects.buffer()); + Assert.assertEquals("A", list.get(0)); + Buffer scalaBuffer = CollectionConverters.asScala(list); + Assert.assertEquals("A", scalaBuffer.head()); + + // scala.collection.mutable.Set <=> java.util.Set + java.util.Set set = CollectionConverters.asJava(TestObjects.mutableSet()); + Assert.assertTrue(set.contains("A")); + Set scalaSet = CollectionConverters.asScala(set); + Assert.assertTrue(scalaSet.contains("A")); + + // scala.collection.mutable.Map <=> java.util.Map + java.util.Map map = CollectionConverters.asJava(TestObjects.mutableMap()); + Assert.assertEquals("B", map.get("A")); + Map scalaMap = CollectionConverters.asScala(map); + Assert.assertEquals("B", scalaMap.get("A").get()); + + // scala.collection.concurrent.Map <=> java.util.concurrent.ConcurrentMap + ConcurrentMap concurrentMap = CollectionConverters.asJava(TestObjects.concurrentMap()); + Assert.assertEquals("B", concurrentMap.get("A")); + scala.collection.concurrent.Map scalaConcurrentMap = CollectionConverters.asScala(concurrentMap); + Assert.assertEquals("B", scalaConcurrentMap.get("A").get()); + } + + /** + * The following conversions are supported via asScala and through specially-named methods to convert to Java collections, as shown: + * + * scala.collection.Iterable <=> java.util.Collection (via asJavaCollection) + * scala.collection.Iterator <=> java.util.Enumeration (via asJavaEnumeration) + * scala.collection.mutable.Map <=> java.util.Dictionary (via asJavaDictionary) + */ + public void convertAsCollection() { + // scala.collection.Iterable <=> java.util.Collection (via asJavaCollection) + Collection collection = CollectionConverters.asJavaCollection(TestObjects.iterable()); + Assert.assertTrue(collection.contains("A")); + Iterable iterable = CollectionConverters.asScala(collection); + Assert.assertEquals("A", iterable.head()); + + // scala.collection.Iterator <=> java.util.Enumeration (via asJavaEnumeration) + Enumeration enumeration = CollectionConverters.asJavaEnumeration(TestObjects.iterator()); + Assert.assertEquals("A", enumeration.nextElement()); + Iterator iterator = CollectionConverters.asScala(enumeration); + Assert.assertEquals("A", iterator.next()); + + // scala.collection.mutable.Map <=> java.util.Dictionary (via asJavaDictionary) + Dictionary dictionary = CollectionConverters.asJavaDictionary(TestObjects.mutableMap()); + Assert.assertEquals("B", dictionary.get("A")); + Map map = CollectionConverters.asScala(dictionary); + Assert.assertEquals("B", map.get("A").get()); + } + + /** In addition, the following one-way conversions are provided via asJava: + * + * scala.collection.Seq => java.util.List + * scala.collection.mutable.Seq => java.util.List + * scala.collection.Set => java.util.Set + * scala.collection.Map => java.util.Map + */ + public void convertsAsJava() { + // scala.collection.Seq => java.util.List + Assert.assertEquals("A", CollectionConverters.asJava(TestObjects.seq()).get(0)); + + // scala.collection.mutable.Seq => java.util.List + Assert.assertEquals("A", CollectionConverters.asJava(TestObjects.mutableSeq()).get(0)); + + // scala.collection.Set => java.util.Set + Assert.assertTrue(CollectionConverters.asJava(TestObjects.set()).contains("A")); + + // scala.collection.Map => java.util.Map + Assert.assertEquals("B", CollectionConverters.asJava(TestObjects.map()).get("A")); + } + + /** + * The following one way conversion is provided via asScala: + * + * java.util.Properties => scala.collection.mutable.Map + */ + public void convertsFromProperties() { + Properties properties = new Properties(); + properties.put("key", "value"); + Map stringStringMap = CollectionConverters.asScala(properties); + Assert.assertEquals("value", stringStringMap.get("key").get()); + } +} diff --git a/compat/src/test/scala-jvm/test/scala/jdk/javaapi/TestObjects.scala b/compat/src/test/scala-jvm/test/scala/jdk/javaapi/TestObjects.scala new file mode 100644 index 00000000..283dd900 --- /dev/null +++ b/compat/src/test/scala-jvm/test/scala/jdk/javaapi/TestObjects.scala @@ -0,0 +1,24 @@ +package test.scala.jdk.javaapi + +import scala.collection.concurrent.TrieMap +import scala.collection.mutable +import scala.collection.mutable.ArrayBuffer +import scala.collection.mutable.Buffer + +/** + * Scala collection objects defined for easy access in a Java class + */ +object TestObjects { + + val seq: scala.collection.Seq[String] = ArrayBuffer("A", "B") + val mutableSeq: scala.collection.mutable.Seq[String] = ArrayBuffer("A", "B") + val set: scala.collection.Set[String] = Set("A", "B") + val map: scala.collection.Map[String, String] = Map("A" -> "B") + + val iterable: scala.collection.Iterable[String] = Iterable("A", "B") + val iterator: scala.collection.Iterator[String] = Iterator("A", "B") + val buffer: scala.collection.mutable.Buffer[String] = mutable.Buffer("A", "B") + val mutableSet: scala.collection.mutable.Set[String] = mutable.Set("A", "B") + val mutableMap: scala.collection.mutable.Map[String, String] = mutable.Map("A" -> "B") + val concurrentMap: scala.collection.concurrent.Map[String, String] = TrieMap("A" -> "B") +}