├── .github └── workflows │ └── checks.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── RELEASE_NOTES.md ├── build.sbt ├── project ├── build.properties └── plugins.sbt ├── scalaj-collection ├── build.sbt └── src │ ├── main │ ├── scala │ │ └── com │ │ │ └── daodecode │ │ │ └── scalaj │ │ │ ├── JavaAliases.scala │ │ │ └── collection │ │ │ ├── JConverter.scala │ │ │ ├── SConverter.scala │ │ │ ├── immutable │ │ │ ├── ImmutableSConverters.scala │ │ │ └── package.scala │ │ │ └── package.scala │ ├── scala_2.13+ │ │ └── com │ │ │ └── daodecode │ │ │ └── scalaj │ │ │ └── collection │ │ │ └── StdLibDecorators.scala │ └── scala_2.13- │ │ └── com │ │ └── daodecode │ │ └── scalaj │ │ └── collection │ │ └── StdLibDecorators.scala │ └── test │ ├── scala │ └── com │ │ └── daodecode │ │ └── scalaj │ │ └── collection │ │ └── test │ │ ├── ComplexJConvertersTest.scala │ │ ├── ComplexSConvertersTest.scala │ │ ├── ScalaJSpec.scala │ │ ├── builders.scala │ │ └── package.scala │ ├── scala_2.13+ │ └── com │ │ └── daodecode │ │ └── scalaj │ │ └── collection │ │ └── test │ │ ├── SimpleJConvertersTest.scala │ │ └── SimpleSConvertersTest.scala │ └── scala_2.13- │ └── com │ └── daodecode │ └── scalaj │ └── collection │ └── test │ ├── SimpleJConvertersTest.scala │ └── SimpleSConvertersTest.scala ├── scalaj-google-optional ├── build.sbt └── src │ ├── main │ └── scala │ │ └── com │ │ └── daodecode │ │ └── scalaj │ │ └── googleoptional │ │ └── package.scala │ └── test │ └── scala │ └── com │ └── daodecode │ └── scalaj │ └── googleoptional │ └── test │ ├── GOptionConvertersTest.scala │ └── ScalaJSpec.scala └── version.sbt /.github/workflows/checks.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | pull_request: 5 | branches: ['**'] 6 | push: 7 | branches: ['**'] 8 | 9 | jobs: 10 | build: 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | matrix: 14 | jvm: 15 | - temurin-jre:1.17.0.7 16 | - graalvm-java11:22.3.2 17 | - zulu:8.0.372 18 | os: 19 | - ubuntu-latest 20 | fail-fast: false 21 | steps: 22 | - name: Checkout current branch (full) 23 | uses: actions/checkout@v2 24 | with: 25 | fetch-depth: 0 26 | submodules: recursive 27 | - uses: coursier/cache-action@v6 28 | - uses: coursier/setup-action@v1 29 | with: 30 | jvm: ${{ matrix.jvm }} 31 | - name: Compile, test and check format, coverage 32 | run: "sbt -batch clean checkFormatting +test scoverage" 33 | shell: bash -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/target 2 | .idea* 3 | token.txt 4 | .bsp -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "scalafmt-config"] 2 | path = scalafmt-config 3 | url = https://github.com/jozic/scalafmt-config.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2015, Eugene Platonov 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the copyright owner nor the names of its contributors 12 | may be used to endorse or promote products derived from this software 13 | without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ScalaJ Converters [![Build Status](https://github.com/jozic/scalaj/actions/workflows/checks.yml/badge.svg?branch=main)](https://github.com/jozic/scalaj/actions/workflows/checks.yml) [![Coverage Status](https://coveralls.io/repos/jozic/scalaj/badge.svg)](https://coveralls.io/r/jozic/scalaj) 2 | ================= 3 | 4 | ### When JavaConverters is not enough... 5 | 6 | If you work on a Java/Scala mixed project you can find yourself converting 7 | java collections and/or primitive wrappers to/from corresponding scala classes or vice versa. 8 | JavaConverters is your friend here, but it's not always good enough. 9 | 10 | If you are tired of doing something like this 11 | 12 | ```scala 13 | import scala.jdk.CollectionConverters._ 14 | 15 | def iTakeInt(i: Int) = { ... } 16 | 17 | val something = someJavaListOfJavaIntegers.asScala.map(iTakeInt(_)) 18 | ``` 19 | 20 | or this 21 | 22 | ```scala 23 | import scala.jdk.CollectionConverters._ 24 | 25 | val something: mutable.Map[java.lang.Long, Buffer] = 26 | someJavaMapOfJavaLongsToJavaLists.asScala.mapValues(_.asScala) 27 | ``` 28 | 29 | look no more! 30 | Now you can do 31 | 32 | ```scala 33 | import com.daodecode.scalaj.collection._ 34 | 35 | def iTakeInt(i: Int) = { ... } 36 | 37 | val something = someJavaListOfJavaIntegers.deepAsScala.map(iTakeInt) 38 | ``` 39 | 40 | and 41 | 42 | ```scala 43 | import com.daodecode.scalaj.collection._ 44 | 45 | val something: mutable.Map[Long, Buffer] = 46 | someJavaMapOfJavaLongsToJavaLists.deepAsScala 47 | ``` 48 | 49 | ScalaJ Converters will go all the way down converting every nested collection or primitive type. 50 | Of course you should be ready to pay some cost for all these conversions. 51 | 52 | Import `import com.daodecode.scalaj.collection._` aslo brings standard `JavaConverters._` in scope, 53 | so you can use plain `asJava/asScala` if you don't have nested collections or collections of primitives. 54 | 55 | Having `scalaj-googloptional` in classpath you can add [guava Optionals](https://github.com/google/guava/blob/master/guava/src/com/google/common/base/Optional.java) to your 56 | funky data structures and convert between them and scala versions all the way down and back. 57 | 58 | ```scala 59 | val foo: java.util.Set[Optional[java.lang.Double] = ... 60 | 61 | import com.daodecode.scalaj.googleoptional._ 62 | 63 | val scalaFoo: mutable.Set[Option[Double]] = foo.deepAsScala 64 | ``` 65 | 66 | If you want you scala collections ~~well-done~~ immutable, you can do it as well 67 | 68 | ```scala 69 | val boo: java.util.Set[Optional[java.util.List[java.lang.Double]] = ... 70 | 71 | import com.daodecode.scalaj.googleoptional._ 72 | import com.daodecode.scalaj.collection.immutable._ 73 | 74 | val immutableScalaBoo: Set[Option[immutable.Seq[Double]]] = boo.deepAsScalaImmutable 75 | ``` 76 | 77 | 78 | # Latest stable release 79 | 80 | ## scalaj-collection 81 | 82 | | 2.10 | 2.11 | 2.12 | 2.13 | 3 | 83 | |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 84 | | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-collection_2.10/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-collection_2.10) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-collection_2.11/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-collection_2.11) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-collection_2.12/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-collection_2.12) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-collection_2.13/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-collection_2.13) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-collection_3/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-collection_3) | 85 | 86 | ### sbt 87 | ```scala 88 | libraryDependencies += "com.daodecode" %% "scalaj-collection" % "0.3.2" 89 | ``` 90 | ### maven 91 | 92 | set `` property to scala version you need, like 93 | 94 | ```xml 95 | 96 | 2.13 97 | 98 | ``` 99 | 100 | and then in `dependencies` add 101 | 102 | ```xml 103 | 104 | com.daodecode 105 | scalaj-collection_${scala.binary.version} 106 | 0.3.2 107 | 108 | ``` 109 | 110 | ## scalaj-googleoptional 111 | 112 | | 2.10 | 2.11 | 2.12 | 2.13 | 3 | 113 | |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 114 | | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-googleoptional_2.10/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-googleoptional_2.10) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-googleoptional_2.11/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-googleoptional_2.11) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-googleoptional_2.12/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-googleoptional_2.12) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-googleoptional_2.13/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-googleoptional_2.13) | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-googleoptional_3/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.daodecode/scalaj-googleoptional_3) | 115 | 116 | ### sbt 117 | 118 | ```scala 119 | libraryDependencies += "com.daodecode" %% "scalaj-googleoptional" % "0.3.2" 120 | ``` 121 | ### maven 122 | 123 | ```xml 124 | 125 | 2.13 126 | 127 | ``` 128 | 129 | and then in `dependencies` add 130 | 131 | ```xml 132 | 133 | com.daodecode 134 | scalaj-googleoptional_${scala.binary.version} 135 | 0.3.2 136 | 137 | ``` 138 | 139 | # Latest snapshot 140 | 141 | First add sonatype snapshots repository to your settings 142 | 143 | ### sbt 144 | 145 | ```scala 146 | resolvers += Resolver.sonatypeRepo("snapshots") 147 | ``` 148 | 149 | ### maven 150 | 151 | ```xml 152 | 153 | snapshots-repo 154 | https://oss.sonatype.org/content/repositories/snapshots 155 | false 156 | true 157 | 158 | ``` 159 | 160 | then add snapshot as a dependency 161 | 162 | ## scalaj-collection 163 | 164 | ### sbt 165 | 166 | ```scala 167 | libraryDependencies += "com.daodecode" %% "scalaj-collection" % "0.3.3-SNAPSHOT" 168 | ``` 169 | 170 | ### maven 171 | 172 | ```xml 173 | 174 | 2.13 175 | 176 | ``` 177 | 178 | and then in `dependencies` add 179 | 180 | ```xml 181 | 182 | com.daodecode 183 | scalaj-collection_${scala.binary.version} 184 | 0.3.3-SNAPSHOT 185 | 186 | ``` 187 | 188 | ## scalaj-googleoptional 189 | 190 | ### sbt 191 | 192 | ```scala 193 | libraryDependencies += "com.daodecode" %% "scalaj-googleoptional" % "0.3.3-SNAPSHOT" 194 | ``` 195 | ### maven 196 | 197 | ```xml 198 | 199 | 2.13 200 | 201 | ``` 202 | 203 | and then in `dependencies` add 204 | 205 | ```xml 206 | 207 | com.daodecode 208 | scalaj-googleoptional_${scala.binary.version} 209 | 0.3.3-SNAPSHOT 210 | 211 | ``` 212 | 213 | # Related projects 214 | 215 | https://github.com/softprops/guavapants 216 | 217 | https://github.com/scalaj/scalaj-collection 218 | -------------------------------------------------------------------------------- /RELEASE_NOTES.md: -------------------------------------------------------------------------------- 1 | 0.1.0 2 | - First release. Convertions between Scala and Java Seqs/Lists, Sets, Maps, primitive wrappers and guava google Optional and Option 3 | 4 | 0.1.1 5 | - Fix pom file broken by bug in sbt 6 | 7 | 0.1.2 8 | - Fix a bug with conversion in Arrays 9 | - Add scaladocs 10 | 11 | 0.2.0 12 | - support scala 2.12 13 | - drop support for scala 2.10 14 | -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | import sbtrelease.ReleasePlugin.autoImport.ReleaseTransformations._ 2 | import scoverage._ 3 | import xerial.sbt.Sonatype._ 4 | 5 | def scala213 = Def.setting(scalaVersion.value.startsWith("2.13")) 6 | def scala3 = Def.setting(scalaVersion.value.startsWith("3.")) 7 | 8 | lazy val crossVersionSourcesSettings = 9 | Seq(Compile, Test).map { sc => 10 | (sc / unmanagedSourceDirectories) ++= { 11 | (sc / unmanagedSourceDirectories).value.flatMap { dir => 12 | if (dir.getPath.endsWith("scala")) 13 | Seq(new File(dir.getPath + (if (scala213.value || scala3.value) "_2.13+" else "_2.13-"))) 14 | else 15 | Seq.empty 16 | } 17 | } 18 | } 19 | 20 | val coverageSettings = Seq( 21 | CoverallsKeys.coverallsTokenFile := Some("./token.txt"), 22 | ScoverageKeys.coverageMinimumStmtTotal := 100, 23 | ScoverageKeys.coverageFailOnMinimum := true, 24 | ScoverageKeys.coverageHighlighting := true 25 | ) 26 | 27 | val releaseSettings = Seq( 28 | releaseCrossBuild := true, 29 | releaseProcess := Seq[ReleaseStep]( 30 | checkSnapshotDependencies, 31 | inquireVersions, 32 | runClean, 33 | runTest, 34 | setReleaseVersion, 35 | commitReleaseVersion, 36 | tagRelease, 37 | releaseStepCommandAndRemaining("+publishSigned"), 38 | releaseStepCommand("sonatypeBundleRelease"), 39 | setNextVersion, 40 | commitNextVersion, 41 | pushChanges 42 | ) 43 | ) 44 | 45 | val publishSettings = sonatypeSettings ++ Seq( 46 | startYear := Some(2015), 47 | homepage := Some(url("http://github.com/jozic/scalaj")), 48 | developers := List( 49 | Developer("jozic", "Eugene Platonov", "jozic@live.com", url("http://github.com/jozic")) 50 | ), 51 | scmInfo := homepage.value.map(ScmInfo(_, "scm:git:git@github.com:jozic/scalaj.git")), 52 | licenses := Seq("BSD-style" -> url("http://www.opensource.org/licenses/BSD-3-Clause")), 53 | publishTo := sonatypePublishToBundle.value 54 | ) 55 | 56 | val commonSettings = Seq( 57 | organization := "com.daodecode", 58 | scalaVersion := "2.13.11", 59 | crossScalaVersions := Seq(scalaVersion.value, "2.12.18", "3.3.0"), 60 | scalafmtConfig := Some(scalaj.base / "scalafmt-config/.scalafmt.conf") 61 | ) ++ releaseSettings ++ crossVersionSourcesSettings 62 | 63 | val Scala212ScalacOptions = Seq( 64 | "-Xlint", 65 | "-unchecked", 66 | "-deprecation", 67 | "-Xfatal-warnings", 68 | "-Ywarn-inaccessible", 69 | "-Ywarn-dead-code", 70 | "-Ywarn-adapted-args", 71 | "-Ywarn-nullary-unit", 72 | "-feature", 73 | "-Ywarn-unused", 74 | "-Ywarn-unused-import", 75 | "-encoding", "UTF-8" 76 | ) 77 | 78 | val Scala213ScalacOptions = Seq( 79 | "-Xlint", 80 | "-unchecked", 81 | "-deprecation", 82 | "-Xfatal-warnings", 83 | "-Ywarn-dead-code", 84 | "-feature", 85 | "-Ywarn-unused", 86 | "-encoding", "UTF-8", 87 | "-Wconf:origin=scala.collection.compat.*:s" 88 | ) 89 | 90 | val Scala3ScalacOptions = Seq( 91 | "-unchecked", 92 | "-deprecation", 93 | "-Werror", 94 | "-feature", 95 | "-encoding", "UTF-8" 96 | ) 97 | 98 | val moduleSettings = commonSettings ++ Seq( 99 | scalacOptions := ( 100 | if (scala3.value) Scala3ScalacOptions 101 | else if (scala213.value) Scala213ScalacOptions 102 | else Scala212ScalacOptions 103 | ), 104 | libraryDependencies ++= Seq( 105 | "org.scalatest" %% "scalatest" % "3.2.16" % "test" 106 | ) 107 | ) ++ publishSettings ++ coverageSettings 108 | 109 | lazy val scalaj: Project = 110 | project 111 | .in(file(".")) 112 | .aggregate(`scalaj-collection`, `scalaj-google-optional`) 113 | .settings( 114 | publishArtifact := false, 115 | publishTo := Some(Resolver.file("Unused transient repository", file("target/unusedrepo"))), 116 | commonSettings 117 | ) 118 | 119 | lazy val `scalaj-collection` = project.settings( 120 | moduleSettings ++ Seq( 121 | libraryDependencies ++= Seq( 122 | "org.scala-lang.modules" %% "scala-collection-compat" % "2.10.0" 123 | ) 124 | ) 125 | ) 126 | 127 | lazy val `scalaj-google-optional` = 128 | project.settings(moduleSettings).dependsOn(`scalaj-collection` % "compile->compile;test->test") 129 | 130 | addCommandAlias("scoverage", ";clean;coverage;test;coverageReport") 131 | 132 | addCommandAlias("checkFormatting", ";scalafmtCheck;test:scalafmtCheck") 133 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.9.0 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.8") 2 | 3 | addSbtPlugin("org.scoverage" %% "sbt-coveralls" % "1.3.8") 4 | 5 | addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.21") 6 | 7 | addSbtPlugin("com.github.sbt" % "sbt-release" % "1.1.0") 8 | 9 | addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") 10 | 11 | addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.6.0-RC4") 12 | 13 | addSbtPlugin("com.thoughtworks.sbt-api-mappings" % "sbt-api-mappings" % "3.0.2") 14 | -------------------------------------------------------------------------------- /scalaj-collection/build.sbt: -------------------------------------------------------------------------------- 1 | name := "scalaj-collection" 2 | 3 | description := "Conversion methods from/to Java/Scala standard library collections" 4 | 5 | console / initialCommands := """ 6 | import com.daodecode.scalaj.collection._ 7 | """ 8 | -------------------------------------------------------------------------------- /scalaj-collection/src/main/scala/com/daodecode/scalaj/JavaAliases.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj 2 | 3 | /** 4 | * Type aliases used for convinience and name conflicts resolution 5 | */ 6 | trait JavaAliases { 7 | type JList[A] = java.util.List[A] 8 | type JSet[A] = java.util.Set[A] 9 | type JMap[A, B] = java.util.Map[A, B] 10 | 11 | type JByte = java.lang.Byte 12 | type JShort = java.lang.Short 13 | type JInt = java.lang.Integer 14 | type JLong = java.lang.Long 15 | type JFloat = java.lang.Float 16 | type JDouble = java.lang.Double 17 | type JChar = java.lang.Character 18 | type JBoolean = java.lang.Boolean 19 | } 20 | 21 | /** 22 | * Companion object for easy import 23 | */ 24 | object JavaAliases extends JavaAliases 25 | -------------------------------------------------------------------------------- /scalaj-collection/src/main/scala/com/daodecode/scalaj/collection/JConverter.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection 2 | 3 | import scala.collection.{Map => GenMap, Seq => GenSeq, Set => GenSet} 4 | import scala.reflect.ClassTag 5 | 6 | /** 7 | * Base trait for convertions of Scala classes to Java classes. 8 | * All deepAsJava methods require implicit parameter of this type 9 | * @tparam A Type convert from (represents Scala side) 10 | * @tparam B Type convert to (represents Java side) 11 | */ 12 | trait JConverter[-A, +B] { 13 | def convert(a: A): B 14 | } 15 | 16 | /** 17 | * Implementation of [[JConverter]] that casts A to B. 18 | * @tparam A Type convert from (represents Scala side) 19 | * @tparam B Type convert to (represents Java side) 20 | */ 21 | class JCastConverter[A, B] extends JConverter[A, B] { 22 | override def convert(a: A): B = a.asInstanceOf[B] 23 | } 24 | 25 | /** 26 | * Converter that "converts" A to A, 27 | * used as a fallback when there are no other implicit converters in scope 28 | */ 29 | object SelfJConverter extends JCastConverter[Any, Any] 30 | 31 | trait LowImplicitSelfJConverter { 32 | 33 | implicit def selfConverter[A]: JConverter[A, A] = SelfJConverter.asInstanceOf[JConverter[A, A]] 34 | } 35 | 36 | /** 37 | * Scala to Java converters for "primitive types 38 | */ 39 | trait PrimitivesJConverter extends LowImplicitSelfJConverter { 40 | 41 | implicit object BytesConverter extends JCastConverter[Byte, JByte] 42 | 43 | implicit object ShortsConverter extends JCastConverter[Short, JShort] 44 | 45 | implicit object IntsConverter extends JCastConverter[Int, JInt] 46 | 47 | implicit object LongsConverter extends JCastConverter[Long, JLong] 48 | 49 | implicit object FloatConverter extends JCastConverter[Float, JFloat] 50 | 51 | implicit object DoublesConverter extends JCastConverter[Double, JDouble] 52 | 53 | implicit object CharConverter extends JCastConverter[Char, JChar] 54 | 55 | implicit object BooleanConverter extends JCastConverter[Boolean, JBoolean] 56 | 57 | } 58 | 59 | /** 60 | * Companion object of [[JConverter]] to bring implicit converters in following order 61 | * - collection converters defined here 62 | * - converters for primitive types defined in [[PrimitivesJConverter]] 63 | * - "self" converter for fallback 64 | */ 65 | object JConverter extends PrimitivesJConverter { 66 | 67 | def apply[A, B](c: A => B): JConverter[A, B] = new JConverter[A, B] { 68 | override def convert(a: A): B = c(a) 69 | } 70 | 71 | /** 72 | * @return converter for converting Scala [[scala.collection.Seq]] to Java [[JList]]. 73 | * Given `converter` used to convert elements of Scala seq 74 | */ 75 | implicit def seqConverter[A, B](implicit converter: JConverter[A, B]): JConverter[GenSeq[A], JList[B]] = 76 | JConverter[GenSeq[A], JList[B]](_.deepAsJava) 77 | 78 | /** 79 | * @return converter for converting Scala [[scala.collection.Set]] to Java [[JSet]]. 80 | * Given `converter` used to convert elements of Scala set 81 | */ 82 | implicit def setConverter[A, B](implicit converter: JConverter[A, B]): JConverter[GenSet[A], JSet[B]] = 83 | JConverter[GenSet[A], JSet[B]](_.deepAsJava) 84 | 85 | /** 86 | * @return converter for converting Java [[scala.Array]] to Java [[scala.Array]] :). 87 | * Given `converter` used to convert elements of the array 88 | */ 89 | implicit def arrayConverter[A, B: ClassTag](implicit converter: JConverter[A, B]): JConverter[Array[A], Array[B]] = 90 | JConverter[Array[A], Array[B]](_.deepAsJava[B]) 91 | 92 | /** 93 | * @return converter for converting Scala [[scala.collection.Map]] to Java [[JMap]]. 94 | * Given `converters` used to convert keys and values of Scala map 95 | */ 96 | implicit def mapConverter[A, B, C, D]( 97 | implicit keyConverter: JConverter[A, C], 98 | valueConverter: JConverter[B, D] 99 | ): JConverter[GenMap[A, B], JMap[C, D]] = 100 | JConverter[GenMap[A, B], JMap[C, D]](_.deepAsJava[C, D]) 101 | } 102 | -------------------------------------------------------------------------------- /scalaj-collection/src/main/scala/com/daodecode/scalaj/collection/SConverter.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection 2 | 3 | import scala.collection.mutable.{Buffer => MBuffer, Map => MMap, Set => MSet} 4 | import scala.reflect.ClassTag 5 | 6 | /** 7 | * Base trait for convertions of Java classes to Scala classes. 8 | * All deepAsScala methods require implicit parameter of this type 9 | * @tparam A Type convert from (represents Java side) 10 | * @tparam B Type convert to (represents Scala side) 11 | */ 12 | trait SConverter[-A, +B] { 13 | def convert(a: A): B 14 | } 15 | 16 | /** 17 | * Implementation of [[SConverter]] that casts A to B. 18 | * @tparam A Type convert from (represents Java side) 19 | * @tparam B Type convert to (represents Scala side) 20 | */ 21 | class SCastConverter[A, B] extends SConverter[A, B] { 22 | override def convert(a: A): B = a.asInstanceOf[B] 23 | } 24 | 25 | /** 26 | * Converter that "converts" A to A, 27 | * used as a fallback when there are no other implicit converters in scope 28 | */ 29 | object SelfSConverter extends SCastConverter[Any, Any] 30 | 31 | trait LowImplicitSelfSConverter { 32 | 33 | implicit def selfConverter[A]: SConverter[A, A] = SelfSConverter.asInstanceOf[SConverter[A, A]] 34 | } 35 | 36 | /** 37 | * Java to Scala converters for "primitive types 38 | */ 39 | trait PrimitivesSConverter extends LowImplicitSelfSConverter { 40 | 41 | implicit object BytesConverter extends SCastConverter[JByte, Byte] 42 | 43 | implicit object ShortsConverter extends SCastConverter[JShort, Short] 44 | 45 | implicit object IntsConverter extends SCastConverter[JInt, Int] 46 | 47 | implicit object LongsConverter extends SCastConverter[JLong, Long] 48 | 49 | implicit object FloatConverter extends SCastConverter[JFloat, Float] 50 | 51 | implicit object DoublesConverter extends SCastConverter[JDouble, Double] 52 | 53 | implicit object CharConverter extends SCastConverter[JChar, Char] 54 | 55 | implicit object BooleanConverter extends SCastConverter[JBoolean, Boolean] 56 | 57 | } 58 | 59 | /** 60 | * Companion object of [[SConverter]] to bring implicit converters in following order 61 | * - collection converters defined here 62 | * - converters for primitive types defined in [[PrimitivesSConverter]] 63 | * - "self" converter for fallback 64 | */ 65 | object SConverter extends PrimitivesSConverter { 66 | 67 | def apply[A, B](c: A => B): SConverter[A, B] = new SConverter[A, B] { 68 | override def convert(a: A): B = c(a) 69 | } 70 | 71 | /** 72 | * @return converter for converting Java [[JList]] to mutable Scala [[scala.collection.mutable.Buffer]]. 73 | * Given `converter` used to convert elements of Java list 74 | */ 75 | implicit def jListConverter[A, B](implicit converter: SConverter[A, B]): SConverter[JList[A], MBuffer[B]] = 76 | SConverter[JList[A], MBuffer[B]](_.deepAsScala) 77 | 78 | /** 79 | * @return converter for converting Java [[JSet]] to mutable Scala [[scala.collection.mutable.Set]]. 80 | * Given `converter` used to convert elements of Java set 81 | */ 82 | implicit def jSetConverter[A, B](implicit converter: SConverter[A, B]): SConverter[JSet[A], MSet[B]] = 83 | SConverter[JSet[A], MSet[B]](_.deepAsScala) 84 | 85 | /** 86 | * @return converter for converting Java [[scala.Array]] to Java [[scala.Array]] :). 87 | * Given `converter` used to convert elements of the array 88 | */ 89 | implicit def arrayConverter[A, B: ClassTag](implicit converter: SConverter[A, B]): SConverter[Array[A], Array[B]] = 90 | SConverter[Array[A], Array[B]](_.deepAsScala[B]) 91 | 92 | /** 93 | * @return converter for converting Java [[JMap]] to mutable Scala [[scala.collection.mutable.Map]]. 94 | * Given `converters` used to convert keys and values of Java map 95 | */ 96 | implicit def jMapConverter[A, B, C, D]( 97 | implicit keyConverter: SConverter[A, C], 98 | valueConverter: SConverter[B, D] 99 | ): SConverter[JMap[A, B], MMap[C, D]] = 100 | SConverter[JMap[A, B], MMap[C, D]](_.deepAsScala[C, D]) 101 | } 102 | -------------------------------------------------------------------------------- /scalaj-collection/src/main/scala/com/daodecode/scalaj/collection/immutable/ImmutableSConverters.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection.immutable 2 | 3 | import com.daodecode.scalaj.collection._ 4 | 5 | import scala.collection.immutable.{Seq => ImSeq} 6 | 7 | /** 8 | * Trait for bringing in implicit [[SCastConverter]]s for converting between Java and immutable Scala collections. 9 | * Importing com.daodecode.scalaj.collection.immutable._ will bring them in the scope. 10 | */ 11 | trait ImmutableSConverters { 12 | 13 | /** 14 | * @return converter for converting Java [[JList]] to immutable Scala [[scala.collection.immutable.Seq]]. 15 | * Given `converter` used to convert elements of Java list 16 | */ 17 | implicit def jListImmutableConverter[A, B](implicit converter: SConverter[A, B]): SConverter[JList[A], ImSeq[B]] = 18 | SConverter[JList[A], ImSeq[B]](_.deepAsScalaImmutable) 19 | 20 | /** 21 | * @return converter for converting Java [[JSet]] to immutable Scala [[scala.collection.immutable.Set]]. 22 | * Given `converter` used to convert elements of Java set 23 | */ 24 | implicit def jSetImmutableConverter[A, B](implicit converter: SConverter[A, B]): SConverter[JSet[A], Set[B]] = 25 | SConverter[JSet[A], Set[B]](_.deepAsScalaImmutable) 26 | 27 | /** 28 | * @return converter for converting Java [[JMap]] to immutable Scala [[scala.collection.immutable.Map]]. 29 | * Given `converters` used to convert keys and values of Java map 30 | */ 31 | implicit def jMapImmutableConverter[A, B, C, D]( 32 | implicit keyConverter: SConverter[A, C], 33 | valueConverter: SConverter[B, D] 34 | ): SConverter[JMap[A, B], Map[C, D]] = 35 | SConverter[JMap[A, B], Map[C, D]](_.deepAsScalaImmutable[C, D]) 36 | } 37 | -------------------------------------------------------------------------------- /scalaj-collection/src/main/scala/com/daodecode/scalaj/collection/immutable/package.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection 2 | 3 | import scala.collection.compat._ 4 | import scala.collection.immutable.{Seq => ImSeq} 5 | 6 | /** 7 | * Importing `com.daodecode.scalaj.collection.immutable._` allows to use "extension" methods deepAsScalaImmutable, 8 | * which convert all supported nested Java collections to immutable versions of corresponding Scala collections 9 | * as well as primitive wrappers. 10 | */ 11 | package object immutable extends ImmutableSConverters { 12 | 13 | implicit class DeepJavaListAsImmutableSeq[A](val javaList: JList[A]) extends AnyVal { 14 | 15 | /** 16 | * Converts given Java [[JList]] to immutable Scala [[scala.collection.immutable.Seq]] 17 | * Elements inside list are converted using given implicit `converter`, 18 | * which allows to convert nested Java collections and primitive wrappers. 19 | * @param converter Implicit converter to convert from `A` to `B`. 20 | * @tparam B New type of resulting Buffer elements 21 | * @return Scala immutable seq. 22 | * 23 | * Example: 24 | * {{{ 25 | * scala> val jl = new java.util.ArrayList[java.util.Set[JInt]]() 26 | * jl: java.util.ArrayList[java.util.Set[com.daodecode.scalaj.collection.JInt]] = [] 27 | * 28 | * scala> jl.add(new java.util.HashSet[JInt]) 29 | * res0: Boolean = true 30 | * 31 | * scala> jl.get(0).add(23) 32 | * res1: Boolean = true 33 | * 34 | * scala> jl 35 | * res2: java.util.ArrayList[java.util.Set[com.daodecode.scalaj.collection.JInt]] = [[23]] 36 | * 37 | * scala> jl.deepAsScalaImmutable 38 | * res3: scala.collection.immutable.Seq[Set[Int]] = Vector(Set(23)) 39 | * }}} 40 | */ 41 | def deepAsScalaImmutable[B](implicit converter: SConverter[A, B]): ImSeq[B] = 42 | javaList.deepAsScala[B].to(ImSeq) 43 | } 44 | 45 | implicit class DeepJavaSetAsImmutableSet[A](val javaSet: JSet[A]) extends AnyVal { 46 | 47 | /** 48 | * Converts given Java [[JSet]] to immutable Scala [[scala.collection.immutable.Set]] 49 | * Elements inside set are converted using given implicit `converter`, 50 | * which allows to convert nested Java collections and primitive wrappers. 51 | * @param converter Implicit converter to convert from `A` to `B`. 52 | * @tparam B New type of resulting Set elements 53 | * @return Scala immutable set. 54 | * 55 | * Example: 56 | * {{{ 57 | * scala> val js = new java.util.HashSet[java.util.Set[JInt]]() 58 | * js: java.util.HashSet[java.util.Set[com.daodecode.scalaj.collection.JInt]] = [] 59 | * 60 | * scala> js.add(new java.util.HashSet[JInt]) 61 | * res0: Boolean = true 62 | * 63 | * scala> js.iterator.next.add(34) 64 | * res1: Boolean = true 65 | * 66 | * scala> js 67 | * res2: java.util.HashSet[java.util.Set[com.daodecode.scalaj.collection.JInt]] = [[34]] 68 | * 69 | * scala> js.deepAsScalaImmutable 70 | * res3: Set[Set[Int]] = Set(Set(34)) 71 | * }}} 72 | */ 73 | def deepAsScalaImmutable[B](implicit converter: SConverter[A, B]): Set[B] = 74 | javaSet.deepAsScala[B].toSet 75 | } 76 | 77 | implicit class DeepJavaMapAsImmutableMap[A, B](val javaMap: JMap[A, B]) extends AnyVal { 78 | 79 | /** 80 | * Converts given Java [[JMap]] to immutable Scala [[scala.collection.immutable.Map]]. 81 | * Keys and values inside map are converted using given implicit `converters`, 82 | * which allow to convert nested Java collections and primitive wrappers. 83 | * @param keyConverter Implicit converter to convert from `A` to `C` 84 | * @param valueConverter Implicit converter to convert from `B` to `D` 85 | * @tparam C New type of Scala map key 86 | * @tparam D New type of Scala map value 87 | * @return Scala immutable map. 88 | * 89 | * Example: 90 | * {{{ 91 | * scala> val jm = new java.util.HashMap[JLong, JList[JChar]]() 92 | * jm: java.util.HashMap[com.daodecode.scalaj.collection.JLong,com.daodecode.scalaj.collection.JList[com.daodecode.scalaj.collection.JChar]] = {} 93 | * 94 | * scala> jm.put(3L, java.util.Arrays.asList('a', 'b', 'c')) 95 | * res0: com.daodecode.scalaj.collection.JList[com.daodecode.scalaj.collection.JChar] = null 96 | * 97 | * scala> jm 98 | * res1: java.util.HashMap[com.daodecode.scalaj.collection.JLong,com.daodecode.scalaj.collection.JList[com.daodecode.scalaj.collection.JChar]] = {3=[a, b, c]} 99 | * 100 | * scala> jm.deepAsScala 101 | * res2: Map[Long,scala.collection.immutable.Seq[Char]] = Map(3 -> Vector(a, b, c)) 102 | * }}} 103 | */ 104 | def deepAsScalaImmutable[C, D]( 105 | implicit keyConverter: SConverter[A, C], 106 | valueConverter: SConverter[B, D] 107 | ): Map[C, D] = 108 | javaMap.deepAsScala[C, D].toMap[C, D] 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /scalaj-collection/src/main/scala/com/daodecode/scalaj/collection/package.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj 2 | 3 | import scala.collection.mutable.{Buffer => MBuffer, Map => MMap, Seq => MSeq, Set => MSet} 4 | import scala.collection.{Map => GenMap, Seq => GenSeq, Set => GenSet} 5 | import scala.reflect.ClassTag 6 | 7 | /** 8 | * Importing `com.daodecode.scalaj.collection._` allows to use "extension" methods deepAsScala/deepAsJava, 9 | * which convert all supported nested Java/Scala collections as well as primitives. 10 | */ 11 | package object collection extends StdLibDecorators with JavaAliases { 12 | 13 | /******************************************** deepAsJava converters ********************************************/ 14 | implicit class DeepSeqAsJavaList[A](val scalaSeq: GenSeq[A]) extends AnyVal { 15 | private def toJava[T](genSeq: GenSeq[T]): JList[T] = genSeq match { 16 | case buffer: MBuffer[_] => buffer.asJava.asInstanceOf[JList[T]] 17 | case mSeq: MSeq[_] => mSeq.asJava.asInstanceOf[JList[T]] 18 | case _ => genSeq.asJava 19 | } 20 | 21 | /** 22 | * Converts given Scala [[scala.collection.Seq]] to Java [[JList]]. 23 | * Elements inside seq are converted using given implicit `converter`, 24 | * which allows to convert nested Scala collections and primitives. 25 | * If given seq is mutable, then returned Java list is mutable as well. 26 | * @param converter Implicit converter to convert from `A` to `B`. 27 | * @tparam B New type of resulting JList elements 28 | * @return Java list wrapper around given seq if given seq elements are primitives 29 | * or anything but supported Scala collections. Wrapper around new seq otherwise. 30 | * 31 | * Example: 32 | * {{{ 33 | * scala> val s = Seq(Seq(1,2), Seq(), Seq(3)) 34 | * s: Seq[Seq[Int]] = List(List(1, 2), List(), List(3)) 35 | * 36 | * scala> s.deepAsJava 37 | * res0: com.daodecode.scalaj.collection.package.JList[com.daodecode.scalaj.collection.JList[com.daodecode.scalaj.collection.JInt]] = [[1, 2], [], [3]] 38 | * }}} 39 | */ 40 | def deepAsJava[B](implicit converter: JConverter[A, B]): JList[B] = { 41 | converter match { 42 | case _: JCastConverter[_, _] => toJava(scalaSeq).asInstanceOf[JList[B]] 43 | case _ => toJava(scalaSeq.map(converter.convert)) 44 | } 45 | } 46 | } 47 | 48 | implicit class DeepSetAsJavaSet[A](val scalaSet: GenSet[A]) extends AnyVal { 49 | private def toJava[T](genSet: GenSet[T]): JSet[T] = genSet match { 50 | case mSet: MSet[T] => mSet.asJava 51 | case _ => genSet.asJava 52 | } 53 | 54 | /** 55 | * Converts given Scala [[scala.collection.Set]] to Java [[JSet]]. 56 | * Elements inside set are converted using given implicit `converter`, 57 | * which allows to convert nested Scala collections and primitives. 58 | * If given set is mutable, then returned Java set is mutable as well. 59 | * @param converter Implicit converter to convert from `A` to `B` 60 | * @tparam B New type of resulting JSet elements 61 | * @return Java set wrapper around given set if given set elements are primitives 62 | * or anything but supported Scala collections. Wrapper around new set otherwise 63 | * 64 | * Example: 65 | * {{{ 66 | * scala> val s = Set(Seq(1,2), Seq(), Seq(3)) 67 | * s: scala.collection.immutable.Set[Seq[Int]] = Set(List(1, 2), List(), List(3)) 68 | * 69 | * scala> s.deepAsJava 70 | * res0: com.daodecode.scalaj.collection.package.JSet[com.daodecode.scalaj.collection.JList[com.daodecode.scalaj.collection.JInt]] = [[1, 2], [], [3]] 71 | * }}} 72 | */ 73 | def deepAsJava[B](implicit converter: JConverter[A, B]): JSet[B] = converter match { 74 | case _: JCastConverter[_, _] => toJava(scalaSet).asInstanceOf[JSet[B]] 75 | case _ => toJava(scalaSet.map(converter.convert)) 76 | } 77 | } 78 | 79 | implicit class DeepArrayAsJavaArray[A](val array: Array[A]) extends AnyVal { 80 | 81 | /** 82 | * Converts given array of A to array of B. 83 | * Elements inside array are converted using given implicit `converter`, 84 | * which allows to convert nested Scala collections and primitives. 85 | * @param converter Implicit converter to convert from `A` to `B` 86 | * @tparam B New type of resulting array elements 87 | * @return Same array if elements of given array are primitives 88 | * or anything but supported Scala collections, new array otherwise 89 | * 90 | * Example: 91 | * {{{ 92 | * scala> val la = Array(Set(1L), Set(2L, 3L)) 93 | * la: Array[scala.collection.immutable.Set[Long]] = Array(Set(1), Set(2, 3)) 94 | * 95 | * scala> la.deepAsJava 96 | * res0: Array[com.daodecode.scalaj.collection.JSet[com.daodecode.scalaj.collection.JLong]] = Array([1], [2, 3]) 97 | * }}} 98 | */ 99 | def deepAsJava[B: ClassTag](implicit converter: JConverter[A, B]): Array[B] = converter match { 100 | case SelfJConverter => array.asInstanceOf[Array[B]] 101 | case _ => array.map(converter.convert) 102 | } 103 | } 104 | 105 | implicit class DeepMapAsJavaMap[A, B](val scalaMap: GenMap[A, B]) extends AnyVal { 106 | private def toJava[T, U](genMap: GenMap[T, U]): JMap[T, U] = genMap match { 107 | case mMap: MMap[_, _] => mMap.asJava.asInstanceOf[JMap[T, U]] 108 | case _ => genMap.asJava 109 | } 110 | 111 | /** 112 | * Converts given Scala [[scala.collection.Map]] to Java [[JMap]]. 113 | * Keys and values inside map are converted using given implicit `converters`, 114 | * which allow to convert nested Scala collections and primitives. 115 | * If given map is mutable, then returned Java map is mutable as well. 116 | * @param keyConverter Implicit converter to convert from `A` to `C` 117 | * @param valueConverter Implicit converter to convert from `B` to `D` 118 | * @tparam C New type of Java map key 119 | * @tparam D New type of Java map value 120 | * @return Java map wrapper around given map if given map keys and values are primitives 121 | * or anything but supported Scala collections. Wrapper around new map otherwise. 122 | * 123 | * Example: 124 | * {{{ 125 | * scala> val m = Map(3L -> Set('3')) 126 | * m: scala.collection.immutable.Map[Long,scala.collection.immutable.Set[Char]] = Map(3 -> Set(3)) 127 | * 128 | * scala> m.deepAsJava 129 | * res0: com.daodecode.scalaj.collection.package.JMap[com.daodecode.scalaj.collection.JLong,com.daodecode.scalaj.collection.JSet[com.daodecode.scalaj.collection.JChar]] = {3=[3]} 130 | * }}} 131 | */ 132 | def deepAsJava[C, D](implicit keyConverter: JConverter[A, C], valueConverter: JConverter[B, D]): JMap[C, D] = 133 | (keyConverter, valueConverter) match { 134 | case (_: JCastConverter[_, _], _: JCastConverter[_, _]) => toJava(scalaMap).asInstanceOf[JMap[C, D]] 135 | case _ => toJava(scalaMap.map { case (k, v) => keyConverter.convert(k) -> valueConverter.convert(v) }) 136 | } 137 | } 138 | 139 | /******************************************** deepAsScala converters ********************************************/ 140 | implicit class DeepJavaListAsMutableBuffer[A](val javaList: JList[A]) extends AnyVal { 141 | 142 | /** 143 | * Converts given Java [[JList]] to mutable Scala [[scala.collection.mutable.Buffer]] 144 | * Elements inside list are converted using given implicit `converter`, 145 | * which allows to convert nested Java collections and primitives. 146 | * @param converter Implicit converter to convert from `A` to `B`. 147 | * @tparam B New type of resulting Buffer elements 148 | * @return Scala wrapper around given list if given list elements are primitives 149 | * or anything but supported Java collections. Wrapper around new list otherwise. 150 | * 151 | * Example: 152 | * {{{ 153 | * scala> val jl = new java.util.ArrayList[java.util.Set[JInt]]() 154 | * jl: java.util.ArrayList[java.util.Set[com.daodecode.scalaj.collection.JInt]] = [] 155 | * 156 | * scala> jl.add(new java.util.HashSet[JInt]) 157 | * res0: Boolean = true 158 | * 159 | * scala> jl.get(0).add(23) 160 | * res1: Boolean = true 161 | * 162 | * scala> jl 163 | * res2: java.util.ArrayList[java.util.Set[com.daodecode.scalaj.collection.JInt]] = [[23]] 164 | * 165 | * scala> jl.deepAsScala 166 | * res3: scala.collection.mutable.Buffer[scala.collection.mutable.Set[Int]] = ArrayBuffer(Set(23)) 167 | * }}} 168 | */ 169 | def deepAsScala[B](implicit converter: SConverter[A, B]): MBuffer[B] = converter match { 170 | case _: SCastConverter[_, _] => javaList.asScala.asInstanceOf[MBuffer[B]] 171 | case _ => javaList.asScala.map(converter.convert) 172 | } 173 | } 174 | 175 | implicit class DeepJavaSetAsMutableSet[A](val javaSet: JSet[A]) extends AnyVal { 176 | 177 | /** 178 | * Converts given Java [[JSet]] to mutable Scala [[scala.collection.mutable.Set]] 179 | * Elements inside set are converted using given implicit `converter`, 180 | * which allows to convert nested Java collections and primitives. 181 | * @param converter Implicit converter to convert from `A` to `B`. 182 | * @tparam B New type of resulting Set elements 183 | * @return Scala wrapper around given Java set if given set elements are primitives 184 | * or anything but supported Java collections. Wrapper around new set otherwise. 185 | * 186 | * Example: 187 | * {{{ 188 | * scala> val js = new java.util.HashSet[java.util.Set[JInt]]() 189 | * js: java.util.HashSet[java.util.Set[com.daodecode.scalaj.collection.JInt]] = [] 190 | * 191 | * scala> js.add(new java.util.HashSet[JInt]) 192 | * res0: Boolean = true 193 | * 194 | * scala> js.iterator.next.add(34) 195 | * res1: Boolean = true 196 | * 197 | * scala> js 198 | * res2: java.util.HashSet[java.util.Set[com.daodecode.scalaj.collection.JInt]] = [[34]] 199 | * 200 | * scala> js.deepAsScala 201 | * res3: scala.collection.mutable.Set[scala.collection.mutable.Set[Int]] = Set(Set(34)) 202 | * }}} 203 | */ 204 | def deepAsScala[B](implicit converter: SConverter[A, B]): MSet[B] = converter match { 205 | case _: SCastConverter[_, _] => javaSet.asScala.asInstanceOf[MSet[B]] 206 | case _ => javaSet.asScala.map(converter.convert) 207 | } 208 | } 209 | 210 | implicit class DeepArrayAsScalaArray[A](val array: Array[A]) extends AnyVal { 211 | 212 | /** 213 | * Converts given array of A to array of B. 214 | * Elements inside array are converted using given implicit `converter`, 215 | * which allows to convert nested Java collections and primitives. 216 | * @param converter Implicit converter to convert from `A` to `B` 217 | * @tparam B New type of resulting array elements 218 | * @return Same array if elements of given array are primitives 219 | * or anything but supported Java collections or primitive wrappers, new array otherwise 220 | * 221 | * Example: 222 | * {{{ 223 | * scala> val ja = Array(java.util.Arrays.asList[JInt](1,2,3)) 224 | * ja: Array[java.util.List[com.daodecode.scalaj.collection.JInt]] = Array([1, 2, 3]) 225 | * 226 | * scala> ja.deepAsScala 227 | * res0: Array[scala.collection.mutable.Buffer[Int]] = Array(Buffer(1, 2, 3)) 228 | * }}} 229 | */ 230 | def deepAsScala[B: ClassTag](implicit converter: SConverter[A, B]): Array[B] = converter match { 231 | case SelfSConverter => array.asInstanceOf[Array[B]] 232 | case _ => array.map(converter.convert) 233 | } 234 | } 235 | 236 | implicit class DeepJavaMapAsMutableMap[A, B](val javaMap: JMap[A, B]) extends AnyVal { 237 | 238 | /** 239 | * Converts given Java [[JMap]] to mutable Scala [[scala.collection.mutable.Map]]. 240 | * Keys and values inside map are converted using given implicit `converters`, 241 | * which allow to convert nested Java collections and primitive wrappers. 242 | * @param keyConverter Implicit converter to convert from `A` to `C` 243 | * @param valueConverter Implicit converter to convert from `B` to `D` 244 | * @tparam C New type of Scala map key 245 | * @tparam D New type of Scala map value 246 | * @return Scala map wrapper around given map if given map keys and values are primitives 247 | * or anything but supported Scala collections or primitive wrappers. Wrapper around new map otherwise. 248 | * 249 | * Example: 250 | * {{{ 251 | * scala> val jm = new java.util.HashMap[JLong, JList[JChar]]() 252 | * jm: java.util.HashMap[com.daodecode.scalaj.collection.JLong,com.daodecode.scalaj.collection.JList[com.daodecode.scalaj.collection.JChar]] = {} 253 | * 254 | * scala> jm.put(3L, java.util.Arrays.asList('a', 'b', 'c')) 255 | * res0: com.daodecode.scalaj.collection.JList[com.daodecode.scalaj.collection.JChar] = null 256 | * 257 | * scala> jm 258 | * res1: java.util.HashMap[com.daodecode.scalaj.collection.JLong,com.daodecode.scalaj.collection.JList[com.daodecode.scalaj.collection.JChar]] = {3=[a, b, c]} 259 | * 260 | * scala> jm.deepAsScala 261 | * res2: scala.collection.mutable.Map[Long,scala.collection.mutable.Buffer[Char]] = Map(3 -> Buffer(a, b, c)) 262 | * }}} 263 | */ 264 | def deepAsScala[C, D](implicit keyConverter: SConverter[A, C], valueConverter: SConverter[B, D]): MMap[C, D] = 265 | (keyConverter, valueConverter) match { 266 | case (_: SCastConverter[_, _], _: SCastConverter[_, _]) => javaMap.asScala.asInstanceOf[MMap[C, D]] 267 | case _ => javaMap.asScala.map { case (k, v) => keyConverter.convert(k) -> valueConverter.convert(v) } 268 | } 269 | } 270 | 271 | } 272 | -------------------------------------------------------------------------------- /scalaj-collection/src/main/scala_2.13+/com/daodecode/scalaj/collection/StdLibDecorators.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection 2 | 3 | import scala.collection.convert.{AsJavaExtensions, AsScalaExtensions} 4 | 5 | trait StdLibDecorators extends AsJavaExtensions with AsScalaExtensions 6 | -------------------------------------------------------------------------------- /scalaj-collection/src/main/scala_2.13-/com/daodecode/scalaj/collection/StdLibDecorators.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection 2 | 3 | import scala.collection.convert.{DecorateAsJava, DecorateAsScala} 4 | 5 | trait StdLibDecorators extends DecorateAsJava with DecorateAsScala 6 | -------------------------------------------------------------------------------- /scalaj-collection/src/test/scala/com/daodecode/scalaj/collection/test/ComplexJConvertersTest.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection.test 2 | 3 | import com.daodecode.scalaj.collection._ 4 | 5 | import scala.collection.mutable.{Buffer => MBuffer, Map => MMap, Seq => MSeq, Set => MSet} 6 | 7 | class ComplexJConvertersTest extends ScalaJSpec { 8 | 9 | "AsJava collection converters" should { 10 | 11 | "convert nested collections and primitives" in { 12 | 13 | List(List(List('a'))).deepAsJava: JList[JList[JList[JChar]]] 14 | 15 | List(MSeq(MBuffer('a'))).deepAsJava: JList[JList[JList[JChar]]] 16 | 17 | List(Map('a' -> 1)).deepAsJava: JList[JMap[JChar, JInt]] 18 | 19 | List(MMap('a' -> 1)).deepAsJava: JList[JMap[JChar, JInt]] 20 | 21 | List(Set(Array(12d))).deepAsJava: JList[JSet[Array[JDouble]]] 22 | 23 | List(Array(Set(12d))).deepAsJava: JList[Array[JSet[JDouble]]] 24 | 25 | Array(List(Set(12L))).deepAsJava: Array[JList[JSet[JLong]]] 26 | 27 | Array(Set(List(false))).deepAsJava: Array[JSet[JList[JBoolean]]] 28 | 29 | Set(List(Array('a'))).deepAsJava: JSet[JList[Array[JChar]]] 30 | 31 | Set(Map(1 -> 'a')).deepAsJava: JSet[JMap[JInt, JChar]] 32 | 33 | Map("set1" -> Set(23, 24)).deepAsJava: JMap[String, JSet[JInt]] 34 | 35 | Map("set1" -> MSet(23, 24)).deepAsJava: JMap[String, JSet[JInt]] 36 | 37 | Map("set1" -> Map(23 -> 'a', 24 -> 'b')).deepAsJava: JMap[String, JMap[JInt, JChar]] 38 | 39 | MMap("set1" -> MMap(23 -> 'a', 24 -> 'b')).deepAsJava: JMap[String, JMap[JInt, JChar]] 40 | } 41 | 42 | "keep nested mutable buffers as mutable" in { 43 | val sm: MSet[MBuffer[Int]] = MSet(MBuffer(1, 2)) 44 | val jm = sm.deepAsJava 45 | 46 | val jList: JList[JInt] = jm.iterator().next() 47 | 48 | jList.add(3) 49 | sm should be(MSet(MBuffer(1, 2, 3))) 50 | } 51 | 52 | "keep nested mutable sets as mutable" in { 53 | val sm: Set[MSet[Int]] = Set(MSet(1, 2)) 54 | val jm = sm.deepAsJava 55 | 56 | val jSet: JSet[JInt] = jm.iterator().next() 57 | 58 | jSet.add(3) 59 | sm should be(Set(MSet(1, 2, 3))) 60 | } 61 | 62 | "keep nested mutable maps as mutable" in { 63 | val sm: MMap[Int, MMap[Long, String]] = MMap(1 -> MMap(2L -> "2")) 64 | val jm = sm.deepAsJava 65 | 66 | val jMap: JMap[JLong, String] = jm.get(1) 67 | 68 | jMap.put(3L, "3") 69 | sm should be(MMap(1 -> MMap(2L -> "2", 3L -> "3"))) 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /scalaj-collection/src/test/scala/com/daodecode/scalaj/collection/test/ComplexSConvertersTest.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection.test 2 | 3 | import com.daodecode.scalaj.collection._ 4 | 5 | import scala.collection.immutable.{Seq => ImSeq} 6 | import scala.collection.mutable.{Buffer => MBuffer, Map => MMap, Set => MSet} 7 | 8 | class ComplexSConvertersTest extends ScalaJSpec with JListBuilder with JSetBuilder with JMapBuilder { 9 | 10 | "AsScala collection converters" should { 11 | 12 | "convert nested collections and primitives" in { 13 | 14 | JList(JList(JList[JChar]('a'))).deepAsScala: MBuffer[MBuffer[MBuffer[Char]]] 15 | 16 | JList(JSet(Array[JDouble](12d))).deepAsScala: MBuffer[MSet[Array[Double]]] 17 | 18 | Array(JList(JSet[JLong](12L))).deepAsScala: Array[MBuffer[MSet[Long]]] 19 | 20 | Array(JSet(JList[JBoolean](false))).deepAsScala: Array[MSet[MBuffer[Boolean]]] 21 | 22 | JSet(JList(Array[JChar]('a'))).deepAsScala: MSet[MBuffer[Array[Char]]] 23 | 24 | JSet(JMap((1: JInt) -> ('a': JChar))).deepAsScala: MSet[MMap[Int, Char]] 25 | 26 | JMap("set1" -> JSet[JInt](23, 24)).deepAsScala: MMap[String, MSet[Int]] 27 | 28 | JMap(Array[JFloat](1f, 2f) -> JList(JSet[JShort](js(23), js(24)))).deepAsScala: MMap[Array[Float], MBuffer[ 29 | MSet[Short] 30 | ]] 31 | } 32 | 33 | "keep nested mutable collections as mutable" in { 34 | 35 | val jm: JSet[JList[JInt]] = JSet(JList[JInt](1, 2)) 36 | val sm = jm.deepAsScala 37 | 38 | val buffer: MBuffer[Int] = sm.head 39 | buffer += 3 40 | 41 | jm.iterator().next() should be(JList[JInt](1, 2, 3)) 42 | } 43 | 44 | "return nested collections as immutable if asked" in { 45 | import com.daodecode.scalaj.collection.immutable._ 46 | 47 | val jm: JList[JList[JInt]] = JList(JList[JInt](1, 2)) 48 | jm.deepAsScalaImmutable: ImSeq[ImSeq[Int]] 49 | 50 | JList(JSet[JChar]('a')).deepAsScalaImmutable: ImSeq[Set[Char]] 51 | 52 | JMap((1L: JLong) -> JList(JSet[JInt](1, 2, 3))).deepAsScalaImmutable: Map[Long, ImSeq[Set[Int]]] 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /scalaj-collection/src/test/scala/com/daodecode/scalaj/collection/test/ScalaJSpec.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection.test 2 | 3 | import org.scalatest.matchers.should.Matchers 4 | import org.scalatest.wordspec.AnyWordSpec 5 | 6 | trait ScalaJSpec extends AnyWordSpec with Matchers 7 | -------------------------------------------------------------------------------- /scalaj-collection/src/test/scala/com/daodecode/scalaj/collection/test/builders.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection.test 2 | 3 | import java.util 4 | 5 | import scala.reflect.ClassTag 6 | 7 | import com.daodecode.scalaj.collection._ 8 | 9 | trait JListBuilder { 10 | def listOf[A, JL <: JList[A]: ClassTag](as: A*): JL = { 11 | val list = newInstance[JL] 12 | as.foreach(list.add) 13 | list 14 | } 15 | 16 | def JList[A](as: A*): JList[A] = listOf[A, util.ArrayList[A]](as: _*) 17 | 18 | } 19 | 20 | trait JSetBuilder { 21 | def setOf[A, JS <: JSet[A]: ClassTag](as: A*): JS = { 22 | val set = newInstance[JS] 23 | as.foreach(set.add) 24 | set 25 | } 26 | 27 | def JSet[A](as: A*): JSet[A] = setOf[A, util.HashSet[A]](as: _*) 28 | } 29 | 30 | trait JMapBuilder { 31 | def mapOf[A, B, JM <: JMap[A, B]: ClassTag](pairs: (A, B)*): JM = { 32 | val jm = newInstance[JM] 33 | pairs.foreach { case (k, v) => jm.put(k, v) } 34 | jm 35 | } 36 | 37 | def JMap[A, B](pairs: (A, B)*): JMap[A, B] = mapOf[A, B, util.HashMap[A, B]](pairs: _*) 38 | } 39 | -------------------------------------------------------------------------------- /scalaj-collection/src/test/scala/com/daodecode/scalaj/collection/test/package.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection 2 | 3 | import scala.reflect.ClassTag 4 | 5 | package object test { 6 | 7 | def jb(b: Byte): JByte = b 8 | 9 | def js(s: Short): JShort = s 10 | 11 | def ji(i: Int): JInt = i 12 | 13 | def newInstance[A: ClassTag]: A = 14 | implicitly[ClassTag[A]].runtimeClass.getDeclaredConstructor().newInstance().asInstanceOf[A] 15 | } 16 | -------------------------------------------------------------------------------- /scalaj-collection/src/test/scala_2.13+/com/daodecode/scalaj/collection/test/SimpleJConvertersTest.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection.test 2 | 3 | import com.daodecode.scalaj.collection._ 4 | 5 | import scala.collection.{immutable, _} 6 | 7 | class SimpleJConvertersTest extends ScalaJSpec { 8 | 9 | "SeqConverters" should { 10 | 11 | def acceptJListOf[A](jl: JList[A]): JList[A] = jl 12 | 13 | def checkMutableSeq[MS[A] <: mutable.Seq[A]](msf: SeqFactory[MS]): Unit = { 14 | val mSeq = msf.empty[Int] :+ 2 15 | mSeq should be(Seq(2)) 16 | mSeq.deepAsJava[Int].set(0, 5) 17 | mSeq should be(Seq(5)) 18 | } 19 | 20 | def checkClassTagMutableSeq[MS[A] <: mutable.Seq[A]](msf: ClassTagSeqFactory[MS]): Unit = { 21 | val mSeq = msf.empty[Int] :+ 2 22 | mSeq should be(Seq(2)) 23 | mSeq.deepAsJava[Int].set(0, 5) 24 | mSeq should be(Seq(5)) 25 | } 26 | 27 | def checkMutableBuffer[MB[A] <: mutable.Buffer[A]](mbf: SeqFactory[MB]): Unit = { 28 | val mBuf = mbf.empty[Int] += 2 29 | mBuf should be(mutable.Buffer(2)) 30 | val jlist = mBuf.deepAsJava[Int] 31 | jlist.set(0, 5) 32 | mBuf should be(mutable.Buffer(5)) 33 | jlist.add(10) 34 | mBuf should be(mutable.Buffer(5, 10)) 35 | } 36 | 37 | "convert lists of primitives properly" in { 38 | 39 | "acceptJListOf[JByte](List[Byte](1, 2, 3))" shouldNot compile 40 | "acceptJListOf[JByte](List[Byte](1, 2, 3).asJava)" shouldNot compile 41 | acceptJListOf[JByte](List[Byte](1, 2, 3).deepAsJava) 42 | 43 | "acceptJListOf[JShort](List(1, 2, 3))" shouldNot compile 44 | "acceptJListOf[JShort](List(1, 2, 3).asJava)" shouldNot compile 45 | acceptJListOf[JShort](List[Short](1, 2, 3).deepAsJava) 46 | 47 | "acceptJListOf[JInt](List(1, 2, 3))" shouldNot compile 48 | "acceptJListOf[JInt](List(1, 2, 3).asJava)" shouldNot compile 49 | acceptJListOf[JInt](List(1, 2, 3).deepAsJava) 50 | 51 | "acceptJListOf[JLong](List(1L, 2L, 3L))" shouldNot compile 52 | "acceptJListOf[JLong](List(1L, 2L, 3L).asJava)" shouldNot compile 53 | acceptJListOf[JLong](List(1L, 2L, 3L).deepAsJava) 54 | 55 | "acceptJListOf[JFloat](List(1F, 2F, 3F))" shouldNot compile 56 | "acceptJListOf[JFloat](List(1F, 2F, 3F).asJava)" shouldNot compile 57 | acceptJListOf[JFloat](List(1f, 2f, 3f).deepAsJava) 58 | 59 | "acceptJListOf[JDouble](List(1D, 2D, 3D))" shouldNot compile 60 | "acceptJListOf[JDouble](List(1D, 2D, 3D).asJava)" shouldNot compile 61 | acceptJListOf[JDouble](List(1d, 2d, 3d).deepAsJava) 62 | 63 | "acceptJListOf[JChar](List('a', 'b'))" shouldNot compile 64 | "acceptJListOf[JChar](List('a', 'b').asJava)" shouldNot compile 65 | acceptJListOf[JChar](List('a', 'b').deepAsJava) 66 | 67 | "acceptJListOf[JBoolean](List(true, false))" shouldNot compile 68 | "acceptJListOf[JBoolean](List(true, false).asJava)" shouldNot compile 69 | acceptJListOf[JBoolean](List(true, false).deepAsJava) 70 | } 71 | 72 | "convert lists of non-primitives properly" in { 73 | case class Boo(i: Int) 74 | acceptJListOf[Boo](List(Boo(3), Boo(5)).asJava) 75 | acceptJListOf[Boo](List(Boo(3), Boo(5)).deepAsJava) 76 | } 77 | 78 | "allow custom converters" in { 79 | implicit val intToString = JConverter[Int, String](i => s"${i}1") 80 | val asJava: JList[String] = List(1, 2, 3).deepAsJava 81 | asJava.get(0) should be("11") 82 | asJava.get(1) should be("21") 83 | asJava.get(2) should be("31") 84 | } 85 | 86 | "support all Seq subclasses" in { 87 | acceptJListOf(List.empty[Int].deepAsJava) 88 | acceptJListOf(List(1).deepAsJava) 89 | acceptJListOf(Vector(1).deepAsJava) 90 | acceptJListOf(LazyList(1).deepAsJava) 91 | acceptJListOf(Seq(1).deepAsJava) 92 | acceptJListOf(immutable.Seq(1).deepAsJava) 93 | acceptJListOf(immutable.IndexedSeq(1).deepAsJava) 94 | acceptJListOf(immutable.LinearSeq(1).deepAsJava) 95 | acceptJListOf(immutable.Queue(1).deepAsJava) 96 | 97 | acceptJListOf(mutable.Seq(1).deepAsJava) 98 | acceptJListOf(mutable.IndexedSeq(1).deepAsJava) 99 | 100 | acceptJListOf(mutable.Buffer(1).deepAsJava) 101 | acceptJListOf(mutable.ArrayBuffer(1).deepAsJava) 102 | acceptJListOf(mutable.ListBuffer(1).deepAsJava) 103 | acceptJListOf(mutable.UnrolledBuffer(1).deepAsJava) 104 | 105 | acceptJListOf(mutable.Queue(1).deepAsJava) 106 | acceptJListOf(mutable.ArraySeq(1).deepAsJava) 107 | } 108 | 109 | "keep mutable seqs mutable" in { 110 | checkMutableSeq(mutable.Seq) 111 | checkMutableSeq(mutable.IndexedSeq) 112 | 113 | checkMutableSeq(mutable.Queue) 114 | 115 | checkMutableSeq(mutable.Buffer) 116 | checkMutableSeq(mutable.ArrayBuffer) 117 | checkMutableSeq(mutable.ListBuffer) 118 | 119 | checkClassTagMutableSeq(mutable.ArraySeq) 120 | checkClassTagMutableSeq(mutable.UnrolledBuffer) 121 | } 122 | 123 | "keep mutable buffers mutable" in { 124 | checkMutableBuffer(mutable.Buffer) 125 | checkMutableBuffer(mutable.ArrayBuffer) 126 | checkMutableBuffer(mutable.ListBuffer) 127 | checkMutableBuffer(mutable.Queue) 128 | checkMutableBuffer(mutable.ArrayDeque) 129 | } 130 | 131 | "return same scala buffer with primitives and self conversions" in { 132 | { 133 | val scalaBuffer = mutable.Buffer(1) 134 | scalaBuffer.deepAsJava.asScala should be theSameInstanceAs scalaBuffer 135 | } 136 | { 137 | val scalaBuffer = mutable.ArrayBuffer(1) 138 | scalaBuffer.deepAsJava.asScala should be theSameInstanceAs scalaBuffer 139 | } 140 | { 141 | val scalaBuffer = mutable.ListBuffer(1) 142 | scalaBuffer.deepAsJava.asScala should be theSameInstanceAs scalaBuffer 143 | } 144 | { 145 | val scalaBuffer = mutable.UnrolledBuffer(1) 146 | scalaBuffer.deepAsJava.asScala should be theSameInstanceAs scalaBuffer 147 | } 148 | { 149 | class A 150 | val scalaBuffer = mutable.Buffer(new A) 151 | scalaBuffer.deepAsJava.asScala should be theSameInstanceAs scalaBuffer 152 | } 153 | } 154 | } 155 | 156 | "ArrayConverters" should { 157 | 158 | def acceptArrayOf[A](ar: Array[A]) = ar 159 | 160 | "convert arrays of primitives properly" in { 161 | "acceptArrayOf[JByte](Array[Byte](1, 2, 3))" shouldNot compile 162 | "acceptArrayOf[JByte](Array[Byte](1, 2, 3).asJava)" shouldNot compile 163 | acceptArrayOf[JByte](Array[Byte](1, 2, 3).deepAsJava) 164 | 165 | "acceptArrayOf[JShort](Array(1, 2, 3))" shouldNot compile 166 | "acceptArrayOf[JShort](Array(1, 2, 3).asJava)" shouldNot compile 167 | acceptArrayOf[JShort](Array[Short](1, 2, 3).deepAsJava) 168 | 169 | "acceptArrayOf[JInt](Array[Int](1, 2, 3))" shouldNot compile 170 | "acceptArrayOf[JInt](Array[Int](1, 2, 3).asJava)" shouldNot compile 171 | acceptArrayOf[JInt](Array[Int](1, 2, 3).deepAsJava) 172 | 173 | "acceptArrayOf[JLong](Array[Long](1L, 2L, 3L))" shouldNot compile 174 | "acceptArrayOf[JLong](Array[Long](1L, 2L, 3L).asJava)" shouldNot compile 175 | acceptArrayOf[JLong](Array[Long](1L, 2L, 3L).deepAsJava) 176 | 177 | "acceptArrayOf[JFloat](Array[Float](1F, 2F, 3F))" shouldNot compile 178 | "acceptArrayOf[JFloat](Array[Float](1F, 2F, 3F).asJava)" shouldNot compile 179 | acceptArrayOf[JFloat](Array[Float](1f, 2f, 3f).deepAsJava) 180 | 181 | "acceptArrayOf[JDouble](Array[Double](1D, 2D, 3D))" shouldNot compile 182 | "acceptArrayOf[JDouble](Array[Double](1D, 2D, 3D).asJava)" shouldNot compile 183 | acceptArrayOf[JDouble](Array[Double](1d, 2d, 3d).deepAsJava) 184 | 185 | "acceptArrayOf[JChar](Array[Char]('a', 'b'))" shouldNot compile 186 | "acceptArrayOf[JChar](Array[Char]('a', 'b').asJava)" shouldNot compile 187 | acceptArrayOf[JChar](Array[Char]('a', 'b').deepAsJava) 188 | 189 | "acceptArrayOf[JBoolean](Array[Boolean](true, false))" shouldNot compile 190 | "acceptArrayOf[JBoolean](Array[Boolean](true, false).asJava)" shouldNot compile 191 | acceptArrayOf[JBoolean](Array[Boolean](true, false).deepAsJava) 192 | } 193 | 194 | "convert arrays of non-primitives properly" in { 195 | case class Boo(i: Int) 196 | "acceptArrayOf[Boo](Array(Boo(3), Boo(5)).asJava)" shouldNot compile 197 | acceptArrayOf[Boo](Array(Boo(3), Boo(5)).deepAsJava) 198 | } 199 | 200 | "allow custom converters" in { 201 | implicit val intToString = JConverter[Int, String](i => s"${i}1") 202 | val asJava: Array[String] = Array(1, 2, 3).deepAsJava 203 | asJava(0) should be("11") 204 | asJava(1) should be("21") 205 | asJava(2) should be("31") 206 | } 207 | 208 | "return same array with self conversions" in { 209 | { 210 | val scalaArray = Array("ss") 211 | scalaArray.deepAsJava[String] should be theSameInstanceAs scalaArray 212 | } 213 | { 214 | class A 215 | val scalaArray = Array(new A) 216 | scalaArray.deepAsJava[A] should be theSameInstanceAs scalaArray 217 | } 218 | } 219 | 220 | } 221 | 222 | "SetConverters" should { 223 | 224 | def acceptJSetOf[A](js: JSet[A]): JSet[A] = js 225 | 226 | def checkMutableSet[MS[A] <: mutable.Set[A]](implicit f: IterableFactory[MS]): Unit = { 227 | val mSet = (f.empty[Int] += 2).result() 228 | mSet should be(Set(2)) 229 | mSet.deepAsJava[Int].add(5) 230 | mSet should be(Set(2, 5)) 231 | } 232 | 233 | def checkMutableSortedSet[MS[A] <: mutable.Set[A]](implicit f: SortedIterableFactory[MS]): Unit = { 234 | val mSet = (f.empty[Int] += 2).result() 235 | mSet should be(Set(2)) 236 | mSet.deepAsJava[Int].add(5) 237 | mSet should be(Set(2, 5)) 238 | } 239 | 240 | "convert sets of primitives properly" in { 241 | 242 | "acceptJSetOf[JByte](Set[Byte](1, 2, 3))" shouldNot compile 243 | "acceptJSetOf[JByte](Set[Byte](1, 2, 3).asJava)" shouldNot compile 244 | acceptJSetOf[JByte](Set[Byte](1, 2, 3).deepAsJava) 245 | 246 | "acceptJSetOf[JShort](Set(1, 2, 3))" shouldNot compile 247 | "acceptJSetOf[JShort](Set(1, 2, 3).asJava)" shouldNot compile 248 | acceptJSetOf[JShort](Set[Short](1, 2, 3).deepAsJava) 249 | 250 | "acceptJSetOf[JInt](Set(1, 2, 3))" shouldNot compile 251 | "acceptJSetOf[JInt](Set(1, 2, 3).asJava)" shouldNot compile 252 | acceptJSetOf[JInt](Set(1, 2, 3).deepAsJava) 253 | 254 | "acceptJSetOf[JLong](Set(1L, 2L, 3L))" shouldNot compile 255 | "acceptJSetOf[JLong](Set(1L, 2L, 3L).asJava)" shouldNot compile 256 | acceptJSetOf[JLong](Set(1L, 2L, 3L).deepAsJava) 257 | 258 | "acceptJSetOf[JFloat](Set(1F, 2F, 3F))" shouldNot compile 259 | "acceptJSetOf[JFloat](Set(1F, 2F, 3F).asJava)" shouldNot compile 260 | acceptJSetOf[JFloat](Set(1f, 2f, 3f).deepAsJava) 261 | 262 | "acceptJSetOf[JDouble](Set(1D, 2D, 3D))" shouldNot compile 263 | "acceptJSetOf[JDouble](Set(1D, 2D, 3D).asJava)" shouldNot compile 264 | acceptJSetOf[JDouble](Set(1d, 2d, 3d).deepAsJava) 265 | 266 | "acceptJSetOf[JChar](Set('a', 'b'))" shouldNot compile 267 | "acceptJSetOf[JChar](Set('a', 'b').asJava)" shouldNot compile 268 | acceptJSetOf[JChar](Set('a', 'b').deepAsJava) 269 | 270 | "acceptJSetOf[JBoolean](Set(true, false))" shouldNot compile 271 | "acceptJSetOf[JBoolean](Set(true, false).asJava)" shouldNot compile 272 | acceptJSetOf[JBoolean](Set(true, false).deepAsJava) 273 | } 274 | 275 | "convert sets of non-primitives properly" in { 276 | case class Boo(i: Int) 277 | acceptJSetOf[Boo](Set(Boo(3), Boo(5)).asJava) 278 | acceptJSetOf[Boo](Set(Boo(3), Boo(5)).deepAsJava) 279 | } 280 | 281 | "allow custom converters" in { 282 | implicit val intToString = JConverter[Int, String](i => s"${i}1") 283 | val asJava: JSet[String] = Set(1, 2, 3).deepAsJava 284 | 285 | asJava should contain("11") 286 | asJava should contain("21") 287 | asJava should contain("31") 288 | } 289 | 290 | "support all Set subclasses" in { 291 | acceptJSetOf(immutable.Set(1).deepAsJava) 292 | acceptJSetOf(immutable.HashSet(1).deepAsJava) 293 | acceptJSetOf(immutable.BitSet(1).deepAsJava) 294 | acceptJSetOf(immutable.ListSet(1).deepAsJava) 295 | acceptJSetOf(immutable.SortedSet(1).deepAsJava) 296 | acceptJSetOf(immutable.TreeSet(1).deepAsJava) 297 | 298 | acceptJSetOf(mutable.Set(1).deepAsJava) 299 | acceptJSetOf(mutable.HashSet(1).deepAsJava) 300 | acceptJSetOf(mutable.BitSet(1).deepAsJava) 301 | acceptJSetOf(mutable.SortedSet(1).deepAsJava) 302 | acceptJSetOf(mutable.TreeSet(1).deepAsJava) 303 | } 304 | 305 | "keep mutable sets mutable" in { 306 | checkMutableSet(mutable.Set) 307 | checkMutableSet(mutable.HashSet) 308 | checkMutableSortedSet(mutable.SortedSet) 309 | checkMutableSortedSet(mutable.TreeSet) 310 | 311 | // check BitSet 312 | val mSet = (mutable.BitSet.empty += 2).result() 313 | mSet should be(Set(2)) 314 | mSet.deepAsJava[Int].add(5) 315 | mSet should be(Set(2, 5)) 316 | } 317 | 318 | "return same mutable scala set with primitives and self conversions" in { 319 | { 320 | val scalaSet = mutable.Set(1) 321 | scalaSet.deepAsJava.asScala should be theSameInstanceAs scalaSet 322 | } 323 | { 324 | val scalaSet = mutable.HashSet(1) 325 | scalaSet.deepAsJava.asScala should be theSameInstanceAs scalaSet 326 | } 327 | { 328 | val scalaSet = mutable.BitSet(1) 329 | scalaSet.deepAsJava.asScala should be theSameInstanceAs scalaSet 330 | } 331 | { 332 | val scalaSet = mutable.SortedSet(1) 333 | scalaSet.deepAsJava.asScala should be theSameInstanceAs scalaSet 334 | } 335 | { 336 | val scalaSet = mutable.TreeSet(1) 337 | scalaSet.deepAsJava.asScala should be theSameInstanceAs scalaSet 338 | } 339 | { 340 | class A 341 | val scalaSet = mutable.Set(new A) 342 | scalaSet.deepAsJava.asScala should be theSameInstanceAs scalaSet 343 | } 344 | } 345 | } 346 | 347 | "MapConverters" should { 348 | 349 | def acceptJMapOf[A, B](jm: JMap[A, B]): JMap[A, B] = jm 350 | 351 | def checkMutableMap[MM[A, B] <: mutable.Map[A, B]](implicit mf: MapFactory[MM]): Unit = { 352 | val mMap = (mf.empty[Int, String] += 2 -> "two").result() 353 | mMap should be(Map(2 -> "two")) 354 | mMap.deepAsJava.put(5, "five") 355 | mMap should be(Map(2 -> "two", 5 -> "five")) 356 | } 357 | 358 | "convert maps of primitives properly" in { 359 | "acceptJMapOf[JByte, JInt](Map[Byte, Int]((1: Byte) -> 2)" shouldNot compile 360 | "acceptJMapOf[JByte, JInt](Map[Byte, Int]((1: Byte) -> 2).asJava)" shouldNot compile 361 | acceptJMapOf[JByte, JInt](Map[Byte, Int]((1: Byte) -> 2).deepAsJava) 362 | 363 | "acceptJMapOf[JShort, JLong](Map[Short, Long]((1: Short) -> 2L)" shouldNot compile 364 | "acceptJMapOf[JShort, JLong](Map[Short, Long]((1: Short) -> 2L).asJava" shouldNot compile 365 | acceptJMapOf[JShort, JLong](Map[Short, Long]((1: Short) -> 2L).deepAsJava) 366 | 367 | "acceptJMapOf[JFloat, JDouble](Map[Float, Double](1F -> 2D)" shouldNot compile 368 | "acceptJMapOf[JFloat, JDouble](Map[Float, Double](1F -> 2D).asJava" shouldNot compile 369 | acceptJMapOf[JFloat, JDouble](Map[Float, Double](1f -> 2d).deepAsJava) 370 | 371 | "acceptJMapOf[JBoolean, JChar](Map[Boolean, Char](true -> 't')" shouldNot compile 372 | "acceptJMapOf[JBoolean, JChar](Map[Boolean, Char](true -> 't').asJava" shouldNot compile 373 | acceptJMapOf[JBoolean, JChar](Map[Boolean, Char](true -> 't').deepAsJava) 374 | } 375 | 376 | "convert maps of non-primitives properly" in { 377 | case class Boo(i: Int) 378 | acceptJMapOf[Boo, String](Map(Boo(3) -> "3", Boo(5) -> "5").asJava) 379 | acceptJMapOf[Boo, String](Map(Boo(3) -> "3", Boo(5) -> "5").deepAsJava) 380 | } 381 | 382 | "allow custom converters" in { 383 | implicit val intToString = JConverter[Int, String](i => s"${i}1") 384 | val asJava: JMap[String, String] = Map("one" -> 1, "two" -> 2, "three" -> 3).deepAsJava 385 | 386 | asJava.get("one") should be("11") 387 | asJava.get("two") should be("21") 388 | asJava.get("three") should be("31") 389 | } 390 | 391 | "support all Map subclasses" in { 392 | acceptJMapOf(immutable.Map(1 -> "one").deepAsJava) 393 | acceptJMapOf(immutable.HashMap(1 -> "one").deepAsJava) 394 | acceptJMapOf(immutable.TreeMap(1 -> "one").deepAsJava) 395 | acceptJMapOf(immutable.SortedMap(1L -> "one").deepAsJava) 396 | acceptJMapOf(immutable.IntMap(1 -> "one").deepAsJava) 397 | acceptJMapOf(immutable.LongMap(1L -> "one").deepAsJava) 398 | acceptJMapOf(immutable.ListMap(1L -> "one").deepAsJava) 399 | 400 | acceptJMapOf(mutable.Map(1 -> "one").deepAsJava) 401 | acceptJMapOf(mutable.HashMap(1 -> "one").deepAsJava) 402 | acceptJMapOf(mutable.LinkedHashMap(1L -> "one").deepAsJava) 403 | acceptJMapOf(mutable.WeakHashMap(1L -> "one").deepAsJava) 404 | } 405 | 406 | "keep mutable maps mutable" in { 407 | checkMutableMap(mutable.Map) 408 | checkMutableMap(mutable.HashMap) 409 | checkMutableMap(mutable.LinkedHashMap) 410 | checkMutableMap(mutable.WeakHashMap) 411 | } 412 | 413 | "return same mutable scala map with primitives and self conversions" in { 414 | { 415 | val scalaMap = mutable.Map(1 -> "one") 416 | scalaMap.deepAsJava.asScala should be theSameInstanceAs scalaMap 417 | } 418 | { 419 | val scalaMap = mutable.HashMap(1 -> "one") 420 | scalaMap.deepAsJava.asScala should be theSameInstanceAs scalaMap 421 | } 422 | { 423 | val scalaMap = mutable.LinkedHashMap(1 -> "one") 424 | scalaMap.deepAsJava.asScala should be theSameInstanceAs scalaMap 425 | } 426 | { 427 | class A 428 | val scalaMap = mutable.Map(new A -> "a") 429 | scalaMap.deepAsJava.asScala should be theSameInstanceAs scalaMap 430 | } 431 | // doesn't hold for WeakHashMap, as it's a wrapper itself 432 | } 433 | } 434 | } 435 | -------------------------------------------------------------------------------- /scalaj-collection/src/test/scala_2.13+/com/daodecode/scalaj/collection/test/SimpleSConvertersTest.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection.test 2 | 3 | import com.daodecode.scalaj.collection._ 4 | 5 | import java.util 6 | import java.util.Arrays.asList 7 | import scala.collection.immutable.{Seq => ImSeq} 8 | import scala.collection.mutable.{Buffer => MBuffer, Map => MMap, Set => MSet} 9 | import scala.reflect.ClassTag 10 | 11 | class SimpleSConvertersTest extends ScalaJSpec with JListBuilder with JSetBuilder with JMapBuilder { 12 | 13 | "JListConverters" should { 14 | 15 | def acceptBufferOf[A](sb: MBuffer[A]): MBuffer[A] = sb 16 | 17 | def checkMutableBuffer[JL <: JList[Int]: ClassTag](): Unit = { 18 | val jList: JL = listOf(2) 19 | jList should be(JList(2)) 20 | 21 | jList.deepAsScala += 5 22 | jList should be(JList(2, 5)) 23 | } 24 | 25 | "convert lists of primitives properly" in { 26 | "acceptBufferOf[Byte](asList[JByte](jb(1), jb(2), jb(3)))" shouldNot compile 27 | "acceptBufferOf[Byte](asList[JByte](jb(1), jb(2), jb(3)).asScala)" shouldNot compile 28 | acceptBufferOf[Byte](asList[JByte](jb(1), jb(2), jb(3)).deepAsScala) 29 | 30 | acceptBufferOf[Short](asList[JShort](js(1), js(2), js(3)).deepAsScala) 31 | acceptBufferOf[Int](asList[JInt](1, 2, 3).deepAsScala) 32 | acceptBufferOf[Long](asList[JLong](1L, 2L, 3L).deepAsScala) 33 | acceptBufferOf[Float](asList[JFloat](1f, 2f, 3f).deepAsScala) 34 | acceptBufferOf[Double](asList[JDouble](1d, 2d, 3d).deepAsScala) 35 | acceptBufferOf[Char](asList[JChar]('a', 'b').deepAsScala) 36 | acceptBufferOf[Boolean](asList[JBoolean](true, false).deepAsScala) 37 | } 38 | 39 | "convert lists of non-primitives properly" in { 40 | case class Boo(i: Int) 41 | "acceptBufferOf[Boo](asList(Boo(3), Boo(5)))" shouldNot compile 42 | acceptBufferOf[Boo](asList(Boo(3), Boo(5)).asScala) 43 | acceptBufferOf[Boo](asList(Boo(3), Boo(5)).deepAsScala) 44 | } 45 | 46 | "allow custom converters" in { 47 | implicit val intToString = SConverter[JInt, String](i => s"${i}1") 48 | val asScala: MBuffer[String] = asList[JInt](1, 2, 3).deepAsScala 49 | asScala(0) should be("11") 50 | asScala(1) should be("21") 51 | asScala(2) should be("31") 52 | } 53 | 54 | "support all standard JList subclasses" in { 55 | acceptBufferOf(new util.ArrayList[JLong]().deepAsScala) 56 | acceptBufferOf(new util.LinkedList[JLong]().deepAsScala) 57 | } 58 | 59 | "keep lists mutable" in { 60 | checkMutableBuffer[util.ArrayList[Int]]() 61 | checkMutableBuffer[util.LinkedList[Int]]() 62 | } 63 | 64 | "return same java list with primitives and self conversions" in { 65 | { 66 | val javaList = new util.ArrayList[JLong]() 67 | javaList.deepAsScala.asJava should be theSameInstanceAs javaList 68 | } 69 | { 70 | val javaList = new util.LinkedList[JLong]() 71 | javaList.deepAsScala.asJava should be theSameInstanceAs javaList 72 | } 73 | { 74 | class A 75 | val javaList = new util.LinkedList[A]() 76 | javaList.deepAsScala.asJava should be theSameInstanceAs javaList 77 | } 78 | } 79 | 80 | "return immutable seq if asked" in { 81 | import com.daodecode.scalaj.collection.immutable._ 82 | 83 | asList[JLong](1L, 2L, 3L).deepAsScalaImmutable: ImSeq[Long] 84 | } 85 | } 86 | 87 | "ArrayConverters" should { 88 | 89 | def acceptArrayOf[A](ar: Array[A]) = ar 90 | 91 | "convert arrays of primitives properly" in { 92 | acceptArrayOf[Byte](Array[JByte](jb(1), jb(2), jb(3)).deepAsScala) 93 | acceptArrayOf[Short](Array[JShort](js(1), js(2), js(3)).deepAsScala) 94 | acceptArrayOf[Int](Array[JInt](1, 2, 3).deepAsScala) 95 | acceptArrayOf[Long](Array[JLong](1L, 2L, 3L).deepAsScala) 96 | acceptArrayOf[Float](Array[JFloat](1f, 2f, 3f).deepAsScala) 97 | acceptArrayOf[Double](Array[JDouble](1d, 2d, 3d).deepAsScala) 98 | acceptArrayOf[Char](Array[JChar]('a', 'b').deepAsScala) 99 | acceptArrayOf[Boolean](Array[JBoolean](true, false).deepAsScala) 100 | } 101 | 102 | "convert arrays of non-primitives properly" in { 103 | case class Boo(i: Int) 104 | acceptArrayOf[Boo](Array(Boo(3), Boo(5)).deepAsScala) 105 | } 106 | 107 | "allow custom converters" in { 108 | implicit val intToString = SConverter[Int, String](i => s"${i}1") 109 | val asScala: Array[String] = Array(1, 2, 3).deepAsScala 110 | asScala(0) should be("11") 111 | asScala(1) should be("21") 112 | asScala(2) should be("31") 113 | } 114 | 115 | "return same array with primitives and self conversions" in { 116 | { 117 | val javaArray = Array[Int](1) 118 | javaArray.deepAsScala[Int] should be theSameInstanceAs javaArray 119 | } 120 | { 121 | val javaArray = Array[Char]('s') 122 | javaArray.deepAsScala[Char] should be theSameInstanceAs javaArray 123 | } 124 | { 125 | val javaArray = Array[Double](12d) 126 | javaArray.deepAsScala[Double] should be theSameInstanceAs javaArray 127 | } 128 | { 129 | class A 130 | val javaArray = Array[A](new A) 131 | javaArray.deepAsScala[A] should be theSameInstanceAs javaArray 132 | } 133 | } 134 | } 135 | 136 | "JSetConverters" should { 137 | 138 | def acceptMSetOf[A](ms: MSet[A]) = ms 139 | 140 | def checkMutableSet[JS <: JSet[Int]: ClassTag](): Unit = { 141 | val mSet: JS = setOf(2) 142 | mSet should be(JSet(2)) 143 | 144 | mSet.deepAsScala += 5 145 | mSet should be(JSet(2, 5)) 146 | } 147 | 148 | "convert sets of primitives properly" in { 149 | acceptMSetOf[Byte](JSet[JByte](jb(1), jb(2), jb(3)).deepAsScala) 150 | acceptMSetOf[Short](JSet[JShort](js(1), js(2), js(3)).deepAsScala) 151 | acceptMSetOf[Int](JSet(1, 2, 3).deepAsScala) 152 | acceptMSetOf[Long](JSet(1L, 2L, 3L).deepAsScala) 153 | acceptMSetOf[Float](JSet(1f, 2f, 3f).deepAsScala) 154 | acceptMSetOf[Double](JSet(1d, 2d, 3d).deepAsScala) 155 | acceptMSetOf[Char](JSet('a', 'b').deepAsScala) 156 | acceptMSetOf[Boolean](JSet(true, false).deepAsScala) 157 | } 158 | 159 | "convert sets of non-primitives properly" in { 160 | case class Boo(i: Int) 161 | acceptMSetOf[Boo](JSet(Boo(3), Boo(5)).asScala) 162 | acceptMSetOf[Boo](JSet(Boo(3), Boo(5)).deepAsScala) 163 | } 164 | 165 | "allow custom converters" in { 166 | implicit val intToString = SConverter[Int, String](i => s"${i}1") 167 | val asScala: MSet[String] = JSet(1, 2, 3).deepAsScala 168 | 169 | asScala should contain("11") 170 | asScala should contain("21") 171 | asScala should contain("31") 172 | } 173 | 174 | "support all standard JSet subclasses" in { 175 | acceptMSetOf(new util.HashSet[JInt]().deepAsScala) 176 | acceptMSetOf(new util.TreeSet[JInt]().deepAsScala) 177 | acceptMSetOf(new util.LinkedHashSet[JInt]().deepAsScala) 178 | } 179 | 180 | "keep sets mutable" in { 181 | checkMutableSet[util.HashSet[Int]]() 182 | checkMutableSet[util.TreeSet[Int]]() 183 | checkMutableSet[util.LinkedHashSet[Int]]() 184 | } 185 | 186 | "return same java set with primitives and self conversions" in { 187 | { 188 | val javaSet = setOf[JInt, util.HashSet[JInt]](1, 2) 189 | javaSet.deepAsScala.asJava should be theSameInstanceAs javaSet 190 | } 191 | { 192 | val javaSet = setOf[JInt, util.TreeSet[JInt]](1, 2) 193 | javaSet.deepAsScala.asJava should be theSameInstanceAs javaSet 194 | } 195 | { 196 | val javaSet = setOf[JInt, util.LinkedHashSet[JInt]](1, 2) 197 | javaSet.deepAsScala.asJava should be theSameInstanceAs javaSet 198 | } 199 | { 200 | class A 201 | val javaSet = setOf[A, util.LinkedHashSet[A]](new A) 202 | javaSet.deepAsScala.asJava should be theSameInstanceAs javaSet 203 | } 204 | } 205 | 206 | "return immutable set if asked" in { 207 | import com.daodecode.scalaj.collection.immutable._ 208 | 209 | JSet[JLong](1L, 2L, 3L).deepAsScalaImmutable: Set[Long] 210 | } 211 | 212 | } 213 | 214 | "JMapConverters" should { 215 | 216 | def acceptMMapOf[A, B](sm: MMap[A, B]) = sm 217 | 218 | def checkMutableMap[JM <: JMap[JInt, String]: ClassTag](): Unit = { 219 | val jMap = mapOf[JInt, String, JM](ji(2) -> "two") 220 | jMap should be(JMap(2 -> "two")) 221 | 222 | jMap.deepAsScala.update(5, "five") 223 | jMap should be(JMap(2 -> "two", 5 -> "five")) 224 | } 225 | 226 | "convert maps of primitives properly" in { 227 | acceptMMapOf[Byte, Int](JMap[JByte, JInt](jb(1) -> 2).deepAsScala) 228 | acceptMMapOf[Short, Long](JMap[JShort, JLong](js(1) -> 2L).deepAsScala) 229 | acceptMMapOf[Float, Double](JMap[JFloat, JDouble]((1f: JFloat) -> (2d: JDouble)).deepAsScala) 230 | acceptMMapOf[Boolean, Char](JMap[JBoolean, JChar]((true: JBoolean) -> ('t': JChar)).deepAsScala) 231 | } 232 | 233 | "convert maps of non-primitives properly" in { 234 | case class Boo(i: Int) 235 | acceptMMapOf[Boo, String](JMap(Boo(3) -> "3", Boo(5) -> "5").asScala) 236 | acceptMMapOf[Boo, String](JMap(Boo(3) -> "3", Boo(5) -> "5").deepAsScala) 237 | } 238 | 239 | "allow custom converters" in { 240 | implicit val intToString = SConverter[Int, String](i => s"${i}1") 241 | val asScala: MMap[String, String] = JMap[String, Int]("one" -> 1, "two" -> 2, "three" -> 3).deepAsScala 242 | 243 | asScala("one") should be("11") 244 | asScala("two") should be("21") 245 | asScala("three") should be("31") 246 | } 247 | 248 | "support all standard Map subclasses" in { 249 | acceptMMapOf(new util.HashMap[JInt, String]().deepAsScala) 250 | acceptMMapOf(new util.IdentityHashMap[JInt, String]().deepAsScala) 251 | acceptMMapOf(new util.LinkedHashMap[JInt, String]().deepAsScala) 252 | acceptMMapOf(new util.TreeMap[JInt, String]().deepAsScala) 253 | acceptMMapOf(new util.WeakHashMap[JInt, String]().deepAsScala) 254 | } 255 | 256 | "keep mutable maps mutable" in { 257 | checkMutableMap[util.HashMap[JInt, String]]() 258 | checkMutableMap[util.IdentityHashMap[JInt, String]]() 259 | checkMutableMap[util.LinkedHashMap[JInt, String]]() 260 | checkMutableMap[util.TreeMap[JInt, String]]() 261 | checkMutableMap[util.WeakHashMap[JInt, String]]() 262 | } 263 | 264 | "return same mutable scala map with primitives and self conversions" in { 265 | { 266 | val javaMap = mapOf[JInt, String, util.HashMap[JInt, String]](ji(1) -> "one") 267 | javaMap.deepAsScala.asJava should be theSameInstanceAs javaMap 268 | } 269 | { 270 | val javaMap = mapOf[JInt, String, util.IdentityHashMap[JInt, String]](ji(1) -> "one") 271 | javaMap.deepAsScala.asJava should be theSameInstanceAs javaMap 272 | } 273 | { 274 | val javaMap = mapOf[JInt, String, util.LinkedHashMap[JInt, String]](ji(1) -> "one") 275 | javaMap.deepAsScala.asJava should be theSameInstanceAs javaMap 276 | } 277 | { 278 | val javaMap = mapOf[JInt, String, util.TreeMap[JInt, String]](ji(1) -> "one") 279 | javaMap.deepAsScala.asJava should be theSameInstanceAs javaMap 280 | } 281 | { 282 | val javaMap = mapOf[JInt, String, util.WeakHashMap[JInt, String]](ji(1) -> "one") 283 | javaMap.deepAsScala.asJava should be theSameInstanceAs javaMap 284 | } 285 | { 286 | class A 287 | val javaMap = mapOf[A, String, util.HashMap[A, String]](new A -> "a") 288 | javaMap.deepAsScala.asJava should be theSameInstanceAs javaMap 289 | } 290 | } 291 | 292 | "return immutable map if asked" in { 293 | import com.daodecode.scalaj.collection.immutable._ 294 | 295 | JMap[String, JDouble]("1" -> 1.0d).deepAsScalaImmutable: Map[String, Double] 296 | } 297 | } 298 | 299 | } 300 | -------------------------------------------------------------------------------- /scalaj-collection/src/test/scala_2.13-/com/daodecode/scalaj/collection/test/SimpleJConvertersTest.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection.test 2 | 3 | import scala.collection.generic.CanBuildFrom 4 | import scala.collection.{immutable, mutable} 5 | 6 | import com.daodecode.scalaj.collection._ 7 | 8 | class SimpleJConvertersTest extends ScalaJSpec { 9 | 10 | "SeqConverters" should { 11 | 12 | def acceptJListOf[A](jl: JList[A]) = jl 13 | 14 | def checkMutableSeq[MS <: mutable.Seq[Int]](implicit cbf: CanBuildFrom[MS, Int, MS]): Unit = { 15 | val mSeq = (cbf() += 2).result() 16 | mSeq should be(Seq(2)) 17 | mSeq.deepAsJava[Int].set(0, 5) 18 | mSeq should be(Seq(5)) 19 | } 20 | 21 | def checkMutableBuffer[MB <: mutable.Buffer[Int]](implicit cbf: CanBuildFrom[MB, Int, MB]): Unit = { 22 | val mBuf = (cbf() += 2).result() 23 | mBuf should be(mutable.Buffer(2)) 24 | val jlist = mBuf.deepAsJava[Int] 25 | jlist.set(0, 5) 26 | mBuf should be(mutable.Buffer(5)) 27 | jlist.add(10) 28 | mBuf should be(mutable.Buffer(5, 10)) 29 | 30 | } 31 | 32 | "convert lists of primitives properly" in { 33 | 34 | "acceptJListOf[JByte](List[Byte](1, 2, 3))" shouldNot compile 35 | "acceptJListOf[JByte](List[Byte](1, 2, 3).asJava)" shouldNot compile 36 | acceptJListOf[JByte](List[Byte](1, 2, 3).deepAsJava) 37 | 38 | "acceptJListOf[JShort](List(1, 2, 3))" shouldNot compile 39 | "acceptJListOf[JShort](List(1, 2, 3).asJava)" shouldNot compile 40 | acceptJListOf[JShort](List[Short](1, 2, 3).deepAsJava) 41 | 42 | "acceptJListOf[JInt](List(1, 2, 3))" shouldNot compile 43 | "acceptJListOf[JInt](List(1, 2, 3).asJava)" shouldNot compile 44 | acceptJListOf[JInt](List(1, 2, 3).deepAsJava) 45 | 46 | "acceptJListOf[JLong](List(1L, 2L, 3L))" shouldNot compile 47 | "acceptJListOf[JLong](List(1L, 2L, 3L).asJava)" shouldNot compile 48 | acceptJListOf[JLong](List(1L, 2L, 3L).deepAsJava) 49 | 50 | "acceptJListOf[JFloat](List(1F, 2F, 3F))" shouldNot compile 51 | "acceptJListOf[JFloat](List(1F, 2F, 3F).asJava)" shouldNot compile 52 | acceptJListOf[JFloat](List(1f, 2f, 3f).deepAsJava) 53 | 54 | "acceptJListOf[JDouble](List(1D, 2D, 3D))" shouldNot compile 55 | "acceptJListOf[JDouble](List(1D, 2D, 3D).asJava)" shouldNot compile 56 | acceptJListOf[JDouble](List(1d, 2d, 3d).deepAsJava) 57 | 58 | "acceptJListOf[JChar](List('a', 'b'))" shouldNot compile 59 | "acceptJListOf[JChar](List('a', 'b').asJava)" shouldNot compile 60 | acceptJListOf[JChar](List('a', 'b').deepAsJava) 61 | 62 | "acceptJListOf[JBoolean](List(true, false))" shouldNot compile 63 | "acceptJListOf[JBoolean](List(true, false).asJava)" shouldNot compile 64 | acceptJListOf[JBoolean](List(true, false).deepAsJava) 65 | } 66 | 67 | "convert lists of non-primitives properly" in { 68 | case class Boo(i: Int) 69 | acceptJListOf[Boo](List(Boo(3), Boo(5)).asJava) 70 | acceptJListOf[Boo](List(Boo(3), Boo(5)).deepAsJava) 71 | } 72 | 73 | "allow custom converters" in { 74 | implicit val intToString = JConverter[Int, String](_ + 1.toString) 75 | val asJava: JList[String] = List(1, 2, 3).deepAsJava 76 | asJava.get(0) should be("11") 77 | asJava.get(1) should be("21") 78 | asJava.get(2) should be("31") 79 | } 80 | 81 | "support all Seq subclasses" in { 82 | acceptJListOf(List.empty[Int].deepAsJava) 83 | acceptJListOf(List(1).deepAsJava) 84 | acceptJListOf(Vector(1).deepAsJava) 85 | acceptJListOf(Stream(1).deepAsJava) 86 | acceptJListOf(Seq(1).deepAsJava) 87 | acceptJListOf(immutable.Seq(1).deepAsJava) 88 | acceptJListOf(immutable.IndexedSeq(1).deepAsJava) 89 | acceptJListOf(immutable.LinearSeq(1).deepAsJava) 90 | acceptJListOf(immutable.Queue(1).deepAsJava) 91 | 92 | acceptJListOf(mutable.Seq(1).deepAsJava) 93 | acceptJListOf(mutable.IndexedSeq(1).deepAsJava) 94 | acceptJListOf(mutable.LinearSeq(1).deepAsJava) 95 | 96 | acceptJListOf(mutable.Buffer(1).deepAsJava) 97 | acceptJListOf(mutable.ArrayBuffer(1).deepAsJava) 98 | acceptJListOf(mutable.ListBuffer(1).deepAsJava) 99 | acceptJListOf(mutable.UnrolledBuffer(1).deepAsJava) 100 | 101 | acceptJListOf(mutable.Queue(1).deepAsJava) 102 | acceptJListOf(mutable.ArrayStack(1).deepAsJava) 103 | acceptJListOf(mutable.ArraySeq(1).deepAsJava) 104 | acceptJListOf(mutable.MutableList(1).deepAsJava) 105 | acceptJListOf(mutable.ResizableArray(1).deepAsJava) 106 | } 107 | 108 | "keep mutable seqs mutable" in { 109 | checkMutableSeq[mutable.Seq[Int]] 110 | checkMutableSeq[mutable.ArraySeq[Int]] 111 | checkMutableSeq[mutable.LinearSeq[Int]] 112 | checkMutableSeq[mutable.IndexedSeq[Int]] 113 | checkMutableSeq[mutable.MutableList[Int]] 114 | checkMutableSeq[mutable.ResizableArray[Int]] 115 | 116 | checkMutableSeq[mutable.Queue[Int]] 117 | checkMutableSeq[mutable.ArrayStack[Int]] 118 | 119 | checkMutableSeq[mutable.Buffer[Int]] 120 | checkMutableSeq[mutable.ArrayBuffer[Int]] 121 | checkMutableSeq[mutable.ListBuffer[Int]] 122 | checkMutableSeq[mutable.UnrolledBuffer[Int]] 123 | } 124 | 125 | "keep mutable buffers mutable" in { 126 | checkMutableBuffer[mutable.Buffer[Int]] 127 | checkMutableBuffer[mutable.ArrayBuffer[Int]] 128 | checkMutableBuffer[mutable.ListBuffer[Int]] 129 | checkMutableBuffer[mutable.UnrolledBuffer[Int]] 130 | } 131 | 132 | "return same scala buffer with primitives and self conversions" in { 133 | { 134 | val scalaBuffer = mutable.Buffer(1) 135 | scalaBuffer.deepAsJava.asScala should be theSameInstanceAs scalaBuffer 136 | } 137 | { 138 | val scalaBuffer = mutable.ArrayBuffer(1) 139 | scalaBuffer.deepAsJava.asScala should be theSameInstanceAs scalaBuffer 140 | } 141 | { 142 | val scalaBuffer = mutable.ListBuffer(1) 143 | scalaBuffer.deepAsJava.asScala should be theSameInstanceAs scalaBuffer 144 | } 145 | { 146 | val scalaBuffer = mutable.UnrolledBuffer(1) 147 | scalaBuffer.deepAsJava.asScala should be theSameInstanceAs scalaBuffer 148 | } 149 | { 150 | class A 151 | val scalaBuffer = mutable.Buffer(new A) 152 | scalaBuffer.deepAsJava.asScala should be theSameInstanceAs scalaBuffer 153 | } 154 | } 155 | } 156 | 157 | "ArrayConverters" should { 158 | 159 | def acceptArrayOf[A](ar: Array[A]) = ar 160 | 161 | "convert arrays of primitives properly" in { 162 | "acceptArrayOf[JByte](Array[Byte](1, 2, 3))" shouldNot compile 163 | "acceptArrayOf[JByte](Array[Byte](1, 2, 3).asJava)" shouldNot compile 164 | acceptArrayOf[JByte](Array[Byte](1, 2, 3).deepAsJava) 165 | 166 | "acceptArrayOf[JShort](Array(1, 2, 3))" shouldNot compile 167 | "acceptArrayOf[JShort](Array(1, 2, 3).asJava)" shouldNot compile 168 | acceptArrayOf[JShort](Array[Short](1, 2, 3).deepAsJava) 169 | 170 | "acceptArrayOf[JInt](Array[Int](1, 2, 3))" shouldNot compile 171 | "acceptArrayOf[JInt](Array[Int](1, 2, 3).asJava)" shouldNot compile 172 | acceptArrayOf[JInt](Array[Int](1, 2, 3).deepAsJava) 173 | 174 | "acceptArrayOf[JLong](Array[Long](1L, 2L, 3L))" shouldNot compile 175 | "acceptArrayOf[JLong](Array[Long](1L, 2L, 3L).asJava)" shouldNot compile 176 | acceptArrayOf[JLong](Array[Long](1L, 2L, 3L).deepAsJava) 177 | 178 | "acceptArrayOf[JFloat](Array[Float](1F, 2F, 3F))" shouldNot compile 179 | "acceptArrayOf[JFloat](Array[Float](1F, 2F, 3F).asJava)" shouldNot compile 180 | acceptArrayOf[JFloat](Array[Float](1f, 2f, 3f).deepAsJava) 181 | 182 | "acceptArrayOf[JDouble](Array[Double](1D, 2D, 3D))" shouldNot compile 183 | "acceptArrayOf[JDouble](Array[Double](1D, 2D, 3D).asJava)" shouldNot compile 184 | acceptArrayOf[JDouble](Array[Double](1d, 2d, 3d).deepAsJava) 185 | 186 | "acceptArrayOf[JChar](Array[Char]('a', 'b'))" shouldNot compile 187 | "acceptArrayOf[JChar](Array[Char]('a', 'b').asJava)" shouldNot compile 188 | acceptArrayOf[JChar](Array[Char]('a', 'b').deepAsJava) 189 | 190 | "acceptArrayOf[JBoolean](Array[Boolean](true, false))" shouldNot compile 191 | "acceptArrayOf[JBoolean](Array[Boolean](true, false).asJava)" shouldNot compile 192 | acceptArrayOf[JBoolean](Array[Boolean](true, false).deepAsJava) 193 | } 194 | 195 | "convert arrays of non-primitives properly" in { 196 | case class Boo(i: Int) 197 | "acceptArrayOf[Boo](Array(Boo(3), Boo(5)).asJava)" shouldNot compile 198 | acceptArrayOf[Boo](Array(Boo(3), Boo(5)).deepAsJava) 199 | } 200 | 201 | "allow custom converters" in { 202 | implicit val intToString = JConverter[Int, String](_ + 1.toString) 203 | val asJava: Array[String] = Array(1, 2, 3).deepAsJava 204 | asJava(0) should be("11") 205 | asJava(1) should be("21") 206 | asJava(2) should be("31") 207 | } 208 | 209 | "return same array with self conversions" in { 210 | { 211 | val scalaArray = Array("ss") 212 | scalaArray.deepAsJava should be theSameInstanceAs scalaArray 213 | } 214 | { 215 | class A 216 | val scalaArray = Array(new A) 217 | scalaArray.deepAsJava should be theSameInstanceAs scalaArray 218 | } 219 | } 220 | 221 | } 222 | 223 | "SetConverters" should { 224 | 225 | def acceptJSetOf[A](js: JSet[A]) = js 226 | 227 | def checkMutableSet[MS <: mutable.Set[Int]](implicit cbf: CanBuildFrom[MS, Int, MS]): Unit = { 228 | val mSet = (cbf() += 2).result() 229 | mSet should be(Set(2)) 230 | mSet.deepAsJava[Int].add(5) 231 | mSet should be(Set(2, 5)) 232 | } 233 | 234 | "convert sets of primitives properly" in { 235 | 236 | "acceptJSetOf[JByte](Set[Byte](1, 2, 3))" shouldNot compile 237 | "acceptJSetOf[JByte](Set[Byte](1, 2, 3).asJava)" shouldNot compile 238 | acceptJSetOf[JByte](Set[Byte](1, 2, 3).deepAsJava) 239 | 240 | "acceptJSetOf[JShort](Set(1, 2, 3))" shouldNot compile 241 | "acceptJSetOf[JShort](Set(1, 2, 3).asJava)" shouldNot compile 242 | acceptJSetOf[JShort](Set[Short](1, 2, 3).deepAsJava) 243 | 244 | "acceptJSetOf[JInt](Set(1, 2, 3))" shouldNot compile 245 | "acceptJSetOf[JInt](Set(1, 2, 3).asJava)" shouldNot compile 246 | acceptJSetOf[JInt](Set(1, 2, 3).deepAsJava) 247 | 248 | "acceptJSetOf[JLong](Set(1L, 2L, 3L))" shouldNot compile 249 | "acceptJSetOf[JLong](Set(1L, 2L, 3L).asJava)" shouldNot compile 250 | acceptJSetOf[JLong](Set(1L, 2L, 3L).deepAsJava) 251 | 252 | "acceptJSetOf[JFloat](Set(1F, 2F, 3F))" shouldNot compile 253 | "acceptJSetOf[JFloat](Set(1F, 2F, 3F).asJava)" shouldNot compile 254 | acceptJSetOf[JFloat](Set(1f, 2f, 3f).deepAsJava) 255 | 256 | "acceptJSetOf[JDouble](Set(1D, 2D, 3D))" shouldNot compile 257 | "acceptJSetOf[JDouble](Set(1D, 2D, 3D).asJava)" shouldNot compile 258 | acceptJSetOf[JDouble](Set(1d, 2d, 3d).deepAsJava) 259 | 260 | "acceptJSetOf[JChar](Set('a', 'b'))" shouldNot compile 261 | "acceptJSetOf[JChar](Set('a', 'b').asJava)" shouldNot compile 262 | acceptJSetOf[JChar](Set('a', 'b').deepAsJava) 263 | 264 | "acceptJSetOf[JBoolean](Set(true, false))" shouldNot compile 265 | "acceptJSetOf[JBoolean](Set(true, false).asJava)" shouldNot compile 266 | acceptJSetOf[JBoolean](Set(true, false).deepAsJava) 267 | } 268 | 269 | "convert sets of non-primitives properly" in { 270 | case class Boo(i: Int) 271 | acceptJSetOf[Boo](Set(Boo(3), Boo(5)).asJava) 272 | acceptJSetOf[Boo](Set(Boo(3), Boo(5)).deepAsJava) 273 | } 274 | 275 | "allow custom converters" in { 276 | implicit val intToString = JConverter[Int, String](_ + 1.toString) 277 | val asJava: JSet[String] = Set(1, 2, 3).deepAsJava 278 | 279 | asJava should contain("11") 280 | asJava should contain("21") 281 | asJava should contain("31") 282 | } 283 | 284 | "support all Set subclasses" in { 285 | acceptJSetOf(immutable.Set(1).deepAsJava) 286 | acceptJSetOf(immutable.HashSet(1).deepAsJava) 287 | acceptJSetOf(immutable.BitSet(1).deepAsJava) 288 | acceptJSetOf(immutable.ListSet(1).deepAsJava) 289 | acceptJSetOf(immutable.SortedSet(1).deepAsJava) 290 | acceptJSetOf(immutable.TreeSet(1).deepAsJava) 291 | 292 | acceptJSetOf(mutable.Set(1).deepAsJava) 293 | acceptJSetOf(mutable.HashSet(1).deepAsJava) 294 | acceptJSetOf(mutable.BitSet(1).deepAsJava) 295 | acceptJSetOf(mutable.SortedSet(1).deepAsJava) 296 | acceptJSetOf(mutable.TreeSet(1).deepAsJava) 297 | } 298 | 299 | "keep mutable sets mutable" in { 300 | checkMutableSet[mutable.Set[Int]] 301 | checkMutableSet[mutable.HashSet[Int]] 302 | checkMutableSet[mutable.BitSet] 303 | checkMutableSet[mutable.SortedSet[Int]] 304 | checkMutableSet[mutable.TreeSet[Int]] 305 | } 306 | 307 | "return same mutable scala set with primitives and self conversions" in { 308 | { 309 | val scalaSet = mutable.Set(1) 310 | scalaSet.deepAsJava.asScala should be theSameInstanceAs scalaSet 311 | } 312 | { 313 | val scalaSet = mutable.HashSet(1) 314 | scalaSet.deepAsJava.asScala should be theSameInstanceAs scalaSet 315 | } 316 | { 317 | val scalaSet = mutable.BitSet(1) 318 | scalaSet.deepAsJava.asScala should be theSameInstanceAs scalaSet 319 | } 320 | { 321 | val scalaSet = mutable.SortedSet(1) 322 | scalaSet.deepAsJava.asScala should be theSameInstanceAs scalaSet 323 | } 324 | { 325 | val scalaSet = mutable.TreeSet(1) 326 | scalaSet.deepAsJava.asScala should be theSameInstanceAs scalaSet 327 | } 328 | { 329 | class A 330 | val scalaSet = mutable.Set(new A) 331 | scalaSet.deepAsJava.asScala should be theSameInstanceAs scalaSet 332 | } 333 | } 334 | } 335 | 336 | "MapConverters" should { 337 | 338 | def acceptJMapOf[A, B](jm: JMap[A, B]) = jm 339 | 340 | def checkMutableMap[MM <: mutable.Map[Int, String]](implicit cbf: CanBuildFrom[MM, (Int, String), MM]): Unit = { 341 | val mMap = (cbf() += 2 -> "two").result() 342 | mMap should be(Map(2 -> "two")) 343 | mMap.deepAsJava.put(5, "five") 344 | mMap should be(Map(2 -> "two", 5 -> "five")) 345 | } 346 | 347 | "convert maps of primitives properly" in { 348 | "acceptJMapOf[JByte, JInt](Map[Byte, Int]((1: Byte) -> 2)" shouldNot compile 349 | "acceptJMapOf[JByte, JInt](Map[Byte, Int]((1: Byte) -> 2).asJava)" shouldNot compile 350 | acceptJMapOf[JByte, JInt](Map[Byte, Int]((1: Byte) -> 2).deepAsJava) 351 | 352 | "acceptJMapOf[JShort, JLong](Map[Short, Long]((1: Short) -> 2L)" shouldNot compile 353 | "acceptJMapOf[JShort, JLong](Map[Short, Long]((1: Short) -> 2L).asJava" shouldNot compile 354 | acceptJMapOf[JShort, JLong](Map[Short, Long]((1: Short) -> 2L).deepAsJava) 355 | 356 | "acceptJMapOf[JFloat, JDouble](Map[Float, Double](1F -> 2D)" shouldNot compile 357 | "acceptJMapOf[JFloat, JDouble](Map[Float, Double](1F -> 2D).asJava" shouldNot compile 358 | acceptJMapOf[JFloat, JDouble](Map[Float, Double](1f -> 2d).deepAsJava) 359 | 360 | "acceptJMapOf[JBoolean, JChar](Map[Boolean, Char](true -> 't')" shouldNot compile 361 | "acceptJMapOf[JBoolean, JChar](Map[Boolean, Char](true -> 't').asJava" shouldNot compile 362 | acceptJMapOf[JBoolean, JChar](Map[Boolean, Char](true -> 't').deepAsJava) 363 | } 364 | 365 | "convert maps of non-primitives properly" in { 366 | case class Boo(i: Int) 367 | acceptJMapOf[Boo, String](Map(Boo(3) -> "3", Boo(5) -> "5").asJava) 368 | acceptJMapOf[Boo, String](Map(Boo(3) -> "3", Boo(5) -> "5").deepAsJava) 369 | } 370 | 371 | "allow custom converters" in { 372 | implicit val intToString = JConverter[Int, String](_ + 1.toString) 373 | val asJava: JMap[String, String] = Map("one" -> 1, "two" -> 2, "three" -> 3).deepAsJava 374 | 375 | asJava.get("one") should be("11") 376 | asJava.get("two") should be("21") 377 | asJava.get("three") should be("31") 378 | } 379 | 380 | "support all Map subclasses" in { 381 | acceptJMapOf(immutable.Map(1 -> "one").deepAsJava) 382 | acceptJMapOf(immutable.HashMap(1 -> "one").deepAsJava) 383 | acceptJMapOf(immutable.TreeMap(1 -> "one").deepAsJava) 384 | acceptJMapOf(immutable.SortedMap(1L -> "one").deepAsJava) 385 | acceptJMapOf(immutable.IntMap(1 -> "one").deepAsJava) 386 | acceptJMapOf(immutable.LongMap(1L -> "one").deepAsJava) 387 | acceptJMapOf(immutable.ListMap(1L -> "one").deepAsJava) 388 | 389 | acceptJMapOf(mutable.Map(1 -> "one").deepAsJava) 390 | acceptJMapOf(mutable.HashMap(1 -> "one").deepAsJava) 391 | acceptJMapOf(mutable.ListMap(1L -> "one").deepAsJava) 392 | acceptJMapOf(mutable.LinkedHashMap(1L -> "one").deepAsJava) 393 | acceptJMapOf(mutable.OpenHashMap(1L -> "one").deepAsJava) 394 | acceptJMapOf(mutable.WeakHashMap(1L -> "one").deepAsJava) 395 | } 396 | 397 | "keep mutable maps mutable" in { 398 | checkMutableMap[mutable.Map[Int, String]] 399 | checkMutableMap[mutable.HashMap[Int, String]] 400 | checkMutableMap[mutable.ListMap[Int, String]] 401 | checkMutableMap[mutable.LinkedHashMap[Int, String]] 402 | checkMutableMap[mutable.WeakHashMap[Int, String]] 403 | 404 | //OpenHashMap doesn't provide CanBuildFrom 405 | val openHashMap: mutable.OpenHashMap[Int, String] = mutable.OpenHashMap(1 -> "one") 406 | openHashMap.deepAsJava.put(2, "two") 407 | openHashMap should be(mutable.OpenHashMap(1 -> "one", 2 -> "two")) 408 | } 409 | 410 | "return same mutable scala map with primitives and self conversions" in { 411 | { 412 | val scalaMap = mutable.Map(1 -> "one") 413 | scalaMap.deepAsJava.asScala should be theSameInstanceAs scalaMap 414 | } 415 | { 416 | val scalaMap = mutable.HashMap(1 -> "one") 417 | scalaMap.deepAsJava.asScala should be theSameInstanceAs scalaMap 418 | } 419 | { 420 | val scalaMap = mutable.ListMap(1 -> "one") 421 | scalaMap.deepAsJava.asScala should be theSameInstanceAs scalaMap 422 | } 423 | { 424 | val scalaMap = mutable.LinkedHashMap(1 -> "one") 425 | scalaMap.deepAsJava.asScala should be theSameInstanceAs scalaMap 426 | } 427 | { 428 | val scalaMap = mutable.OpenHashMap(1 -> "one") 429 | scalaMap.deepAsJava.asScala should be theSameInstanceAs scalaMap 430 | } 431 | { 432 | class A 433 | val scalaMap = mutable.Map(new A -> "a") 434 | scalaMap.deepAsJava.asScala should be theSameInstanceAs scalaMap 435 | } 436 | // doesn't hold for WeakHashMap, as it's a wrapper itself 437 | } 438 | } 439 | } 440 | -------------------------------------------------------------------------------- /scalaj-collection/src/test/scala_2.13-/com/daodecode/scalaj/collection/test/SimpleSConvertersTest.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.collection.test 2 | 3 | import java.util 4 | import java.util.Arrays.asList 5 | 6 | import scala.collection.immutable.{Seq => ImSeq} 7 | import scala.collection.mutable.{Buffer => MBuffer, Map => MMap, Set => MSet} 8 | import scala.reflect.ClassTag 9 | 10 | import com.daodecode.scalaj.collection._ 11 | 12 | class SimpleSConvertersTest extends ScalaJSpec with JListBuilder with JSetBuilder with JMapBuilder { 13 | 14 | "JListConverters" should { 15 | 16 | def acceptBufferOf[A](sb: MBuffer[A]) = sb 17 | 18 | def checkMutableBuffer[JL <: JList[Int]: ClassTag](): Unit = { 19 | val jList: JL = listOf(2) 20 | jList should be(JList(2)) 21 | 22 | jList.deepAsScala += 5 23 | jList should be(JList(2, 5)) 24 | } 25 | 26 | "convert lists of primitives properly" in { 27 | "acceptBufferOf[Byte](asList[JByte](jb(1), jb(2), jb(3)))" shouldNot compile 28 | "acceptBufferOf[Byte](asList[JByte](jb(1), jb(2), jb(3)).asScala)" shouldNot compile 29 | acceptBufferOf[Byte](asList[JByte](jb(1), jb(2), jb(3)).deepAsScala) 30 | 31 | acceptBufferOf[Short](asList[JShort](js(1), js(2), js(3)).deepAsScala) 32 | acceptBufferOf[Int](asList[JInt](1, 2, 3).deepAsScala) 33 | acceptBufferOf[Long](asList[JLong](1L, 2L, 3L).deepAsScala) 34 | acceptBufferOf[Float](asList[JFloat](1f, 2f, 3f).deepAsScala) 35 | acceptBufferOf[Double](asList[JDouble](1d, 2d, 3d).deepAsScala) 36 | acceptBufferOf[Char](asList[JChar]('a', 'b').deepAsScala) 37 | acceptBufferOf[Boolean](asList[JBoolean](true, false).deepAsScala) 38 | } 39 | 40 | "convert lists of non-primitives properly" in { 41 | case class Boo(i: Int) 42 | "acceptBufferOf[Boo](asList(Boo(3), Boo(5)))" shouldNot compile 43 | acceptBufferOf[Boo](asList(Boo(3), Boo(5)).asScala) 44 | acceptBufferOf[Boo](asList(Boo(3), Boo(5)).deepAsScala) 45 | } 46 | 47 | "allow custom converters" in { 48 | implicit val intToString = SConverter[JInt, String](_ + 1.toString) 49 | val asScala: MBuffer[String] = asList[JInt](1, 2, 3).deepAsScala 50 | asScala(0) should be("11") 51 | asScala(1) should be("21") 52 | asScala(2) should be("31") 53 | } 54 | 55 | "support all standard JList subclasses" in { 56 | acceptBufferOf(new util.ArrayList[JLong]().deepAsScala) 57 | acceptBufferOf(new util.LinkedList[JLong]().deepAsScala) 58 | } 59 | 60 | "keep lists mutable" in { 61 | checkMutableBuffer[util.ArrayList[Int]]() 62 | checkMutableBuffer[util.LinkedList[Int]]() 63 | } 64 | 65 | "return same java list with primitives and self conversions" in { 66 | { 67 | val javaList = new util.ArrayList[JLong]() 68 | javaList.deepAsScala.asJava should be theSameInstanceAs javaList 69 | } 70 | { 71 | val javaList = new util.LinkedList[JLong]() 72 | javaList.deepAsScala.asJava should be theSameInstanceAs javaList 73 | } 74 | { 75 | class A 76 | val javaList = new util.LinkedList[A]() 77 | javaList.deepAsScala.asJava should be theSameInstanceAs javaList 78 | } 79 | } 80 | 81 | "return immutable seq if asked" in { 82 | import com.daodecode.scalaj.collection.immutable._ 83 | 84 | asList[JLong](1L, 2L, 3L).deepAsScalaImmutable: ImSeq[Long] 85 | } 86 | } 87 | 88 | "ArrayConverters" should { 89 | 90 | def acceptArrayOf[A](ar: Array[A]) = ar 91 | 92 | "convert arrays of primitives properly" in { 93 | acceptArrayOf[Byte](Array[JByte](jb(1), jb(2), jb(3)).deepAsScala) 94 | acceptArrayOf[Short](Array[JShort](js(1), js(2), js(3)).deepAsScala) 95 | acceptArrayOf[Int](Array[JInt](1, 2, 3).deepAsScala) 96 | acceptArrayOf[Long](Array[JLong](1L, 2L, 3L).deepAsScala) 97 | acceptArrayOf[Float](Array[JFloat](1f, 2f, 3f).deepAsScala) 98 | acceptArrayOf[Double](Array[JDouble](1d, 2d, 3d).deepAsScala) 99 | acceptArrayOf[Char](Array[JChar]('a', 'b').deepAsScala) 100 | acceptArrayOf[Boolean](Array[JBoolean](true, false).deepAsScala) 101 | } 102 | 103 | "convert arrays of non-primitives properly" in { 104 | case class Boo(i: Int) 105 | acceptArrayOf[Boo](Array(Boo(3), Boo(5)).deepAsScala) 106 | } 107 | 108 | "allow custom converters" in { 109 | implicit val intToString = SConverter[Int, String](_ + 1.toString) 110 | val asScala: Array[String] = Array(1, 2, 3).deepAsScala 111 | asScala(0) should be("11") 112 | asScala(1) should be("21") 113 | asScala(2) should be("31") 114 | } 115 | 116 | "return same array with primitives and self conversions" in { 117 | { 118 | val javaArray = Array[Int](1) 119 | javaArray.deepAsScala should be theSameInstanceAs javaArray 120 | } 121 | { 122 | val javaArray = Array[Char]('s') 123 | javaArray.deepAsScala should be theSameInstanceAs javaArray 124 | } 125 | { 126 | val javaArray = Array[Double](12d) 127 | javaArray.deepAsScala should be theSameInstanceAs javaArray 128 | } 129 | { 130 | class A 131 | val javaArray = Array[A](new A) 132 | javaArray.deepAsScala should be theSameInstanceAs javaArray 133 | } 134 | } 135 | } 136 | 137 | "JSetConverters" should { 138 | 139 | def acceptMSetOf[A](ms: MSet[A]) = ms 140 | 141 | def checkMutableSet[JS <: JSet[Int]: ClassTag](): Unit = { 142 | val mSet: JS = setOf(2) 143 | mSet should be(JSet(2)) 144 | 145 | mSet.deepAsScala += 5 146 | mSet should be(JSet(2, 5)) 147 | } 148 | 149 | "convert sets of primitives properly" in { 150 | acceptMSetOf[Byte](JSet[JByte](jb(1), jb(2), jb(3)).deepAsScala) 151 | acceptMSetOf[Short](JSet[JShort](js(1), js(2), js(3)).deepAsScala) 152 | acceptMSetOf[Int](JSet(1, 2, 3).deepAsScala) 153 | acceptMSetOf[Long](JSet(1L, 2L, 3L).deepAsScala) 154 | acceptMSetOf[Float](JSet(1f, 2f, 3f).deepAsScala) 155 | acceptMSetOf[Double](JSet(1d, 2d, 3d).deepAsScala) 156 | acceptMSetOf[Char](JSet('a', 'b').deepAsScala) 157 | acceptMSetOf[Boolean](JSet(true, false).deepAsScala) 158 | } 159 | 160 | "convert sets of non-primitives properly" in { 161 | case class Boo(i: Int) 162 | acceptMSetOf[Boo](JSet(Boo(3), Boo(5)).asScala) 163 | acceptMSetOf[Boo](JSet(Boo(3), Boo(5)).deepAsScala) 164 | } 165 | 166 | "allow custom converters" in { 167 | implicit val intToString = SConverter[Int, String](_ + 1.toString) 168 | val asScala: MSet[String] = JSet(1, 2, 3).deepAsScala 169 | 170 | asScala should contain("11") 171 | asScala should contain("21") 172 | asScala should contain("31") 173 | } 174 | 175 | "support all standard JSet subclasses" in { 176 | acceptMSetOf(new util.HashSet[JInt]().deepAsScala) 177 | acceptMSetOf(new util.TreeSet[JInt]().deepAsScala) 178 | acceptMSetOf(new util.LinkedHashSet[JInt]().deepAsScala) 179 | } 180 | 181 | "keep sets mutable" in { 182 | checkMutableSet[util.HashSet[Int]]() 183 | checkMutableSet[util.TreeSet[Int]]() 184 | checkMutableSet[util.LinkedHashSet[Int]]() 185 | } 186 | 187 | "return same java set with primitives and self conversions" in { 188 | { 189 | val javaSet = setOf[JInt, util.HashSet[JInt]](1, 2) 190 | javaSet.deepAsScala.asJava should be theSameInstanceAs javaSet 191 | } 192 | { 193 | val javaSet = setOf[JInt, util.TreeSet[JInt]](1, 2) 194 | javaSet.deepAsScala.asJava should be theSameInstanceAs javaSet 195 | } 196 | { 197 | val javaSet = setOf[JInt, util.LinkedHashSet[JInt]](1, 2) 198 | javaSet.deepAsScala.asJava should be theSameInstanceAs javaSet 199 | } 200 | { 201 | class A 202 | val javaSet = setOf[A, util.LinkedHashSet[A]](new A) 203 | javaSet.deepAsScala.asJava should be theSameInstanceAs javaSet 204 | } 205 | } 206 | 207 | "return immutable set if asked" in { 208 | import com.daodecode.scalaj.collection.immutable._ 209 | 210 | JSet[JLong](1L, 2L, 3L).deepAsScalaImmutable: Set[Long] 211 | } 212 | 213 | } 214 | 215 | "JMapConverters" should { 216 | 217 | def acceptMMapOf[A, B](sm: MMap[A, B]) = sm 218 | 219 | def checkMutableMap[JM <: JMap[JInt, String]: ClassTag](): Unit = { 220 | val jMap = mapOf[JInt, String, JM](ji(2) -> "two") 221 | jMap should be(JMap(2 -> "two")) 222 | 223 | jMap.deepAsScala update (5, "five") 224 | jMap should be(JMap(2 -> "two", 5 -> "five")) 225 | } 226 | 227 | "convert maps of primitives properly" in { 228 | acceptMMapOf[Byte, Int](JMap[JByte, JInt](jb(1) -> 2).deepAsScala) 229 | acceptMMapOf[Short, Long](JMap[JShort, JLong](js(1) -> 2L).deepAsScala) 230 | acceptMMapOf[Float, Double](JMap[JFloat, JDouble]((1f: JFloat) -> (2d: JDouble)).deepAsScala) 231 | acceptMMapOf[Boolean, Char](JMap[JBoolean, JChar]((true: JBoolean) -> ('t': JChar)).deepAsScala) 232 | } 233 | 234 | "convert maps of non-primitives properly" in { 235 | case class Boo(i: Int) 236 | acceptMMapOf[Boo, String](JMap(Boo(3) -> "3", Boo(5) -> "5").asScala) 237 | acceptMMapOf[Boo, String](JMap(Boo(3) -> "3", Boo(5) -> "5").deepAsScala) 238 | } 239 | 240 | "allow custom converters" in { 241 | implicit val intToString = SConverter[Int, String](_ + 1.toString) 242 | val asScala: MMap[String, String] = JMap[String, Int]("one" -> 1, "two" -> 2, "three" -> 3).deepAsScala 243 | 244 | asScala("one") should be("11") 245 | asScala("two") should be("21") 246 | asScala("three") should be("31") 247 | } 248 | 249 | "support all standard Map subclasses" in { 250 | acceptMMapOf(new util.HashMap[JInt, String]().deepAsScala) 251 | acceptMMapOf(new util.IdentityHashMap[JInt, String]().deepAsScala) 252 | acceptMMapOf(new util.LinkedHashMap[JInt, String]().deepAsScala) 253 | acceptMMapOf(new util.TreeMap[JInt, String]().deepAsScala) 254 | acceptMMapOf(new util.WeakHashMap[JInt, String]().deepAsScala) 255 | } 256 | 257 | "keep mutable maps mutable" in { 258 | checkMutableMap[util.HashMap[JInt, String]]() 259 | checkMutableMap[util.IdentityHashMap[JInt, String]]() 260 | checkMutableMap[util.LinkedHashMap[JInt, String]]() 261 | checkMutableMap[util.TreeMap[JInt, String]]() 262 | checkMutableMap[util.WeakHashMap[JInt, String]]() 263 | } 264 | 265 | "return same mutable scala map with primitives and self conversions" in { 266 | { 267 | val javaMap = mapOf[JInt, String, util.HashMap[JInt, String]](ji(1) -> "one") 268 | javaMap.deepAsScala.asJava should be theSameInstanceAs javaMap 269 | } 270 | { 271 | val javaMap = mapOf[JInt, String, util.IdentityHashMap[JInt, String]](ji(1) -> "one") 272 | javaMap.deepAsScala.asJava should be theSameInstanceAs javaMap 273 | } 274 | { 275 | val javaMap = mapOf[JInt, String, util.LinkedHashMap[JInt, String]](ji(1) -> "one") 276 | javaMap.deepAsScala.asJava should be theSameInstanceAs javaMap 277 | } 278 | { 279 | val javaMap = mapOf[JInt, String, util.TreeMap[JInt, String]](ji(1) -> "one") 280 | javaMap.deepAsScala.asJava should be theSameInstanceAs javaMap 281 | } 282 | { 283 | val javaMap = mapOf[JInt, String, util.WeakHashMap[JInt, String]](ji(1) -> "one") 284 | javaMap.deepAsScala.asJava should be theSameInstanceAs javaMap 285 | } 286 | { 287 | class A 288 | val javaMap = mapOf[A, String, util.HashMap[A, String]](new A -> "a") 289 | javaMap.deepAsScala.asJava should be theSameInstanceAs javaMap 290 | } 291 | } 292 | 293 | "return immutable map if asked" in { 294 | import com.daodecode.scalaj.collection.immutable._ 295 | 296 | JMap[String, JDouble]("1" -> 1.0d).deepAsScalaImmutable: Map[String, Double] 297 | } 298 | } 299 | 300 | } 301 | -------------------------------------------------------------------------------- /scalaj-google-optional/build.sbt: -------------------------------------------------------------------------------- 1 | name := "scalaj-googleoptional" 2 | 3 | description := "Conversions for google guava optional" 4 | 5 | libraryDependencies += "com.google.guava" % "guava" % "10.0" % "provided" 6 | 7 | console / initialCommands := """ 8 | import com.daodecode.scalaj.googleoptional._ 9 | """ 10 | -------------------------------------------------------------------------------- /scalaj-google-optional/src/main/scala/com/daodecode/scalaj/googleoptional/package.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj 2 | 3 | import com.daodecode.scalaj.collection._ 4 | import com.google.common.base.{Optional => GOption} 5 | 6 | /** 7 | * Importing `com.daodecode.scalaj.googleoptional._` allows to use "extension" methods 8 | * asJava/asScala, deepAsScala/deepAsJava. 9 | * The later handle all nested Options/Optionals as well as primitives. 10 | */ 11 | package object googleoptional { 12 | 13 | type GOption[A] = com.google.common.base.Optional[A] 14 | 15 | implicit class DeepOptionAsOptional[A](val option: Option[A]) extends AnyVal { 16 | 17 | /** 18 | * Converts given [[scala.Option]] to [[com.google.common.base.Optional]]. 19 | * Object inside Option is NOT converted. 20 | * @return `Absent` if option is `None` or `Some(null)`, `Present` otherwise 21 | * 22 | * Example: 23 | * {{{ 24 | * scala> Option(12).asJava 25 | * res0: com.daodecode.scalaj.googleoptional.package.GOption[Int] = Optional.of(12) 26 | * }}} 27 | */ 28 | def asJava: GOption[A] = 29 | option.fold(GOption.absent[A])(a => GOption.fromNullable(a)) 30 | 31 | /** 32 | * Converts given [[scala.Option]] to [[com.google.common.base.Optional]]. 33 | * Object inside Option is converted using implicit `converter`. 34 | * All scala primitives will be implicitly converted to corresponding java primitive type wrappers. 35 | * This method allows for many level of conversions as long as proper implicit converter is in scope. 36 | * @param converter Implicit converter to convert from `A` to `B` 37 | * @tparam B New type of Optional 38 | * @return `Absent` if option is `None` or if converted value is `null`, `Present` otherwise 39 | * 40 | * Example: 41 | * {{{ 42 | * scala> Option(12).deepAsJava 43 | * res0: com.daodecode.scalaj.googleoptional.package.GOption[com.daodecode.scalaj.collection.JInt] = Optional.of(12) 44 | * 45 | * scala> Option(Option(12)).deepAsJava 46 | * res1: com.daodecode.scalaj.googleoptional.package.GOption[ 47 | * com.daodecode.scalaj.googleoptional.GOption[com.daodecode.scalaj.collection.JInt]] = 48 | * Optional.of(Optional.of(12)) 49 | * }}} 50 | */ 51 | def deepAsJava[B](implicit converter: JConverter[A, B]): GOption[B] = 52 | option.fold(GOption.absent[B])(a => GOption.fromNullable(converter.convert(a))) 53 | } 54 | 55 | implicit class DeepOptionalAsOption[A](val optional: GOption[A]) extends AnyVal { 56 | 57 | /** 58 | * Converts [[com.google.common.base.Optional]] to [[scala.Option]]. 59 | * Object inside `optional` is NOT converted 60 | * @return `Some` if `optional` is `Present`, `None` otherwise 61 | * 62 | * Example: 63 | * {{{ 64 | * scala> Optional.of(12: JInt).asScala 65 | * res0: Option[com.daodecode.scalaj.JavaAliases.JInt] = Some(12) 66 | * }}} 67 | */ 68 | def asScala: Option[A] = 69 | if (optional.isPresent) 70 | Some(optional.get()) 71 | else 72 | None 73 | 74 | /** 75 | * Converts given [[com.google.common.base.Optional]] to [[scala.Option]]. 76 | * Object inside Option is converted using implicit `converter`. 77 | * All java primitive type wrappers will be implicitly converted to corresponding scala primitives. 78 | * This method allows for many level of conversions as long as proper implicit converter is in scope. 79 | * @param converter Implicit converter to convert from `A` to `B` 80 | * @tparam B New type of Option 81 | * @return `Some` if optional is `Absent`, `None` otherwise 82 | * 83 | * Example: 84 | * {{{ 85 | * scala> Optional.of(12: JInt).deepAsScala 86 | * res0: Option[Int] = Some(12) 87 | * 88 | * scala> Optional.of(Optional.of(12: JInt)).deepAsScala 89 | * res1: Option[Option[Int]] = Some(Some(12)) 90 | * }}} 91 | */ 92 | def deepAsScala[B](implicit converter: SConverter[A, B]): Option[B] = 93 | if (optional.isPresent) 94 | Some(converter.convert(optional.get())) 95 | else 96 | None 97 | } 98 | 99 | /** 100 | * Implicit converter that lifts `JConverter[A, B]` to `JConverter[Option[A], GOption[B]]` 101 | * @param converter Implicit converter to convert from `A` to `B` 102 | * @tparam A Original type 103 | * @tparam B Type after conversion 104 | * @return New `JConverter` that can convert `Option[A]` to `GOption[B]` 105 | */ 106 | implicit def optionConverter[A, B](implicit converter: JConverter[A, B]): JConverter[Option[A], GOption[B]] = 107 | JConverter[Option[A], GOption[B]](_.deepAsJava) 108 | 109 | /** 110 | * Implicit converter that lifts `SConverter[A, B]` to `SConverter[GOption[A], Option[B]]` 111 | * @param converter Implicit converter to convert from `A` to `B` 112 | * @tparam A Original type 113 | * @tparam B Type after conversion 114 | * @return New `SConverter` that can convert `GOption[A]` to `Option[B]` 115 | */ 116 | implicit def optionalConverter[A, B](implicit converter: SConverter[A, B]): SConverter[GOption[A], Option[B]] = 117 | SConverter[GOption[A], Option[B]](_.deepAsScala) 118 | } 119 | -------------------------------------------------------------------------------- /scalaj-google-optional/src/test/scala/com/daodecode/scalaj/googleoptional/test/GOptionConvertersTest.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.googleoptional.test 2 | 3 | import com.daodecode.scalaj.JavaAliases._ 4 | import com.daodecode.scalaj.collection.test.{JMapBuilder, JSetBuilder} 5 | import com.daodecode.scalaj.googleoptional._ 6 | import com.google.common.base.{Optional => GOption} 7 | 8 | import scala.collection.mutable.{Map => MMap, Set => MSet} 9 | 10 | class GOptionConvertersTest extends ScalaJSpec with JSetBuilder with JMapBuilder { 11 | 12 | def jb(b: Byte): JByte = b 13 | 14 | def sb(b: Byte): Byte = b 15 | 16 | def js(s: Short): JShort = s 17 | 18 | def ss(s: Short): Short = s 19 | 20 | "DeepAsJava Converter" should { 21 | 22 | class A 23 | 24 | "convert Somes with primitives and any non collection types properly" in { 25 | 26 | def checkPresent[T](optional: GOption[T], expected: T): Unit = { 27 | optional.get() should be(expected) 28 | } 29 | 30 | checkPresent(Option(1: Byte).deepAsJava, expected = jb(1)) 31 | checkPresent(Option(1: Short).deepAsJava, expected = js(1)) 32 | 33 | checkPresent(Option(1).deepAsJava, expected = 1: JInt) 34 | checkPresent(Option(1L).deepAsJava, expected = 1L: JLong) 35 | checkPresent(Option(1f).deepAsJava, expected = 1f: JFloat) 36 | checkPresent(Option(1d).deepAsJava, expected = 1d: JDouble) 37 | checkPresent(Option('a').deepAsJava, expected = 'a': JChar) 38 | checkPresent(Option(true).deepAsJava, expected = true: JBoolean) 39 | 40 | val a = new A 41 | checkPresent(Option(a).deepAsJava, expected = a) 42 | } 43 | 44 | "convert Nones with primitives and any non-collection types properly" in { 45 | 46 | def checkAbsent[T](optional: GOption[T]): Unit = { 47 | optional should be(GOption.absent[T]) 48 | } 49 | 50 | checkAbsent[JByte](Option.empty[Byte].deepAsJava) 51 | checkAbsent[JShort](Option.empty[Short].deepAsJava) 52 | checkAbsent[JInt](Option.empty[Int].deepAsJava) 53 | checkAbsent[JLong](Option.empty[Long].deepAsJava) 54 | checkAbsent[JFloat](Option.empty[Float].deepAsJava) 55 | checkAbsent[JDouble](Option.empty[Double].deepAsJava) 56 | checkAbsent[JChar](Option.empty[Char].deepAsJava) 57 | checkAbsent[JBoolean](Option.empty[Boolean].deepAsJava) 58 | 59 | checkAbsent[A](Option.empty[A].deepAsJava) 60 | } 61 | 62 | "convert Some of null to absent, as Optional can't have nulls" in { 63 | Some[A](null).deepAsJava should be(GOption.absent[A]) 64 | } 65 | 66 | "convert nested options" in { 67 | val asJava = Option(Option(2d)).deepAsJava 68 | asJava shouldBe a[GOption[_]] 69 | asJava.get shouldBe a[GOption[_]] 70 | 71 | Option(Option(2d)).deepAsJava: GOption[GOption[JDouble]] 72 | } 73 | 74 | "convert collections in options" in { 75 | val asJava = Option(Set(2d)).deepAsJava 76 | asJava shouldBe a[GOption[_]] 77 | asJava.get() shouldBe a[JSet[_]] 78 | 79 | Option(Set(2d)).deepAsJava: GOption[JSet[JDouble]] 80 | } 81 | 82 | "convert options in collections" in { 83 | import com.daodecode.scalaj.collection._ 84 | 85 | val asJava = Set(Option(2d)).deepAsJava 86 | asJava shouldBe a[JSet[_]] 87 | asJava.iterator().next() shouldBe a[GOption[_]] 88 | 89 | val asJava2 = Option(Map(Option(2L) -> Set(Option('a')))).deepAsJava 90 | asJava2 shouldBe a[GOption[_]] 91 | asJava2.get shouldBe a[JMap[_, _]] 92 | asJava2.get.keySet().iterator().next() shouldBe a[GOption[_]] 93 | asJava2.get.values().iterator().next() shouldBe a[JSet[_]] 94 | asJava2.get.values().iterator().next().iterator().next() shouldBe a[GOption[_]] 95 | 96 | Option(Map(Option(2L) -> Set(Option('a')))).deepAsJava: GOption[JMap[GOption[JLong], JSet[GOption[JChar]]]] 97 | } 98 | } 99 | 100 | "AsJava Converter" should { 101 | 102 | class A 103 | 104 | "convert Somes without touching primitives " in { 105 | 106 | def checkPresent[T](optional: GOption[T], expected: T): Unit = { 107 | optional.get() should be(expected) 108 | } 109 | 110 | checkPresent(Option(sb(1)).asJava, expected = sb(1)) 111 | checkPresent(Option(ss(1)).asJava, expected = ss(1)) 112 | checkPresent(Option(1).asJava, expected = 1) 113 | checkPresent(Option(1L).asJava, expected = 1L) 114 | checkPresent(Option(1f).asJava, expected = 1f) 115 | checkPresent(Option(1d).asJava, expected = 1d) 116 | checkPresent(Option('a').asJava, expected = 'a') 117 | checkPresent(Option(true).asJava, expected = true) 118 | 119 | val a = new A 120 | checkPresent(Option(a).deepAsJava, expected = a) 121 | } 122 | 123 | "convert Nones properly" in { 124 | 125 | def checkAbsent[T](optional: GOption[T]): Unit = { 126 | optional should be(GOption.absent[T]) 127 | } 128 | 129 | checkAbsent[Byte](Option.empty[Byte].asJava) 130 | checkAbsent[Short](Option.empty[Short].asJava) 131 | checkAbsent[Int](Option.empty[Int].asJava) 132 | checkAbsent[Long](Option.empty[Long].asJava) 133 | checkAbsent[Float](Option.empty[Float].asJava) 134 | checkAbsent[Double](Option.empty[Double].asJava) 135 | checkAbsent[Char](Option.empty[Char].asJava) 136 | checkAbsent[Boolean](Option.empty[Boolean].asJava) 137 | 138 | checkAbsent[A](Option.empty[A].asJava) 139 | } 140 | 141 | "convert Some of null to absent, as Optional can't have nulls" in { 142 | Some[A](null).asJava should be(GOption.absent[A]) 143 | } 144 | 145 | "convert NOT nested options" in { 146 | val asJava = Option(Option(2d)).asJava 147 | asJava shouldBe a[GOption[_]] 148 | asJava.get shouldBe a[Option[_]] 149 | 150 | Option(Option(2d)).asJava: GOption[Option[Double]] 151 | } 152 | 153 | "convert NOT collections in options" in { 154 | val asJava = Option(Set(2d)).asJava 155 | asJava shouldBe a[GOption[_]] 156 | asJava.get() shouldBe a[Set[_]] 157 | 158 | Option(Set(2d)).asJava: GOption[Set[Double]] 159 | } 160 | } 161 | 162 | "DeepAsScala Converter" should { 163 | 164 | class A 165 | 166 | "convert Presents with primitives and any non-collection types properly" in { 167 | 168 | def checkSome[T](option: Option[T], expected: T): Unit = { 169 | option.get should be(expected) 170 | } 171 | 172 | checkSome[Byte](GOption.of(jb(1)).deepAsScala, expected = 1: Byte) 173 | checkSome[Short](GOption.of(js(1)).deepAsScala, expected = 1: Short) 174 | checkSome[Int](GOption.of(1: JInt).deepAsScala, expected = 1) 175 | checkSome[Long](GOption.of(1L: JLong).deepAsScala, expected = 1L) 176 | checkSome[Float](GOption.of(1f: JFloat).deepAsScala, expected = 1f) 177 | checkSome[Double](GOption.of(1d: JDouble).deepAsScala, expected = 1d) 178 | checkSome[Char](GOption.of('a': JChar).deepAsScala, expected = 'a') 179 | checkSome[Boolean](GOption.of(false: JBoolean).deepAsScala, expected = false) 180 | 181 | val a = new A 182 | checkSome[A](GOption.of(a).deepAsScala, expected = a) 183 | } 184 | 185 | "convert Absents with primitives and any non collection types properly" in { 186 | 187 | def checkNone[T](option: Option[T]): Unit = { 188 | option should be(None) 189 | } 190 | 191 | checkNone[Byte](GOption.absent[JByte].deepAsScala) 192 | checkNone[Short](GOption.absent[JShort].deepAsScala) 193 | checkNone[Int](GOption.absent[JInt].deepAsScala) 194 | checkNone[Long](GOption.absent[JLong].deepAsScala) 195 | checkNone[Float](GOption.absent[JFloat].deepAsScala) 196 | checkNone[Double](GOption.absent[JDouble].deepAsScala) 197 | checkNone[Char](GOption.absent[JChar].deepAsScala) 198 | checkNone[Boolean](GOption.absent[JBoolean].deepAsScala) 199 | 200 | checkNone[A](GOption.absent[A].deepAsScala) 201 | } 202 | 203 | "convert nested options" in { 204 | val asScala = GOption.of(GOption.of[JDouble](2d)).deepAsScala 205 | 206 | asScala shouldBe an[Option[_]] 207 | asScala.get shouldBe an[Option[_]] 208 | 209 | GOption.of(GOption.of[JDouble](2d)).deepAsScala: Option[Option[Double]] 210 | } 211 | 212 | "convert collections in options" in { 213 | //requires type ascription 214 | val asScala = GOption.of(JSet[JDouble](2d)).deepAsScala 215 | asScala shouldBe an[Option[_]] 216 | asScala.get shouldBe an[MSet[_]] 217 | 218 | GOption.of(JSet[JDouble](2d)).deepAsScala: Option[MSet[Double]] 219 | } 220 | 221 | "convert options in collections" in { 222 | import com.daodecode.scalaj.collection._ 223 | 224 | val asScala = JSet(GOption.of[JDouble](2d)).deepAsScala 225 | asScala shouldBe an[MSet[_]] 226 | asScala.head shouldBe an[Option[_]] 227 | 228 | JSet(GOption.of[JDouble](2d)).deepAsScala: MSet[Option[Double]] 229 | 230 | val asScala2 = GOption.of(JMap(GOption.of[JLong](2L) -> JSet(GOption.of[JChar]('a')))).deepAsScala 231 | asScala2 shouldBe an[Option[_]] 232 | asScala2.get shouldBe an[MMap[_, _]] 233 | asScala2.get.head._1 shouldBe an[Option[_]] 234 | asScala2.get.head._2 shouldBe an[MSet[_]] 235 | asScala2.get.head._2.head shouldBe an[Option[_]] 236 | 237 | GOption 238 | .of(JMap(GOption.of[JLong](2L) -> JSet(GOption.of[JChar]('a')))) 239 | .deepAsScala: Option[MMap[Option[Long], MSet[Option[Char]]]] 240 | } 241 | } 242 | 243 | "DeepAsScalaImmutable Converter" should { 244 | "convert nested collections as immutable if asked" in { 245 | import com.daodecode.scalaj.collection.immutable._ 246 | 247 | val asScala = GOption.of(JSet[JDouble](2d)).deepAsScala 248 | asScala shouldBe an[Option[_]] 249 | asScala.get shouldBe an[Set[_]] 250 | 251 | GOption.of(JSet[JDouble](2d)).deepAsScala: Option[Set[Double]] 252 | } 253 | 254 | "convert collections in options in collections as immutable if asked" in { 255 | import com.daodecode.scalaj.collection.immutable._ 256 | 257 | val asScala = JSet(GOption.of[JDouble](2d)).deepAsScalaImmutable 258 | asScala shouldBe an[Set[_]] 259 | asScala.head shouldBe an[Option[_]] 260 | 261 | JSet(GOption.of[JDouble](2d)).deepAsScalaImmutable: Set[Option[Double]] 262 | 263 | val asScala2 = GOption.of(JMap(GOption.of[JLong](2L) -> JSet(GOption.of[JChar]('a')))).deepAsScala 264 | asScala2 shouldBe an[Option[_]] 265 | asScala2.get shouldBe an[Map[_, _]] 266 | asScala2.get.head._1 shouldBe an[Option[_]] 267 | asScala2.get.head._2 shouldBe an[Set[_]] 268 | asScala2.get.head._2.head shouldBe an[Option[_]] 269 | 270 | GOption 271 | .of(JMap(GOption.of[JLong](2L) -> JSet(GOption.of[JChar]('a')))) 272 | .deepAsScala: Option[Map[Option[Long], Set[Option[Char]]]] 273 | } 274 | 275 | } 276 | 277 | "AsScala Converter" should { 278 | 279 | class A 280 | 281 | "convert Presents without touching primitives" in { 282 | 283 | def checkSome[T](option: Option[T], expected: T): Unit = { 284 | option.get should be(expected) 285 | } 286 | 287 | checkSome[JByte](GOption.of(jb(1)).asScala, expected = jb(1)) 288 | checkSome[JShort](GOption.of(js(1)).asScala, expected = js(1)) 289 | checkSome[JInt](GOption.of(1: JInt).asScala, expected = 1: JInt) 290 | checkSome[JLong](GOption.of(1L: JLong).asScala, expected = 1L: JLong) 291 | checkSome[JFloat](GOption.of(1f: JFloat).asScala, expected = 1f: JFloat) 292 | checkSome[JDouble](GOption.of(1d: JDouble).asScala, expected = 1d: JDouble) 293 | checkSome[JChar](GOption.of('a': JChar).asScala, expected = 'a': JChar) 294 | checkSome[JBoolean](GOption.of(false: JBoolean).asScala, expected = false: JBoolean) 295 | 296 | val a = new A 297 | checkSome[A](GOption.of(a).asScala, expected = a) 298 | } 299 | 300 | "convert Absents properly" in { 301 | 302 | def checkNone[T](option: Option[T]): Unit = { 303 | option should be(None) 304 | } 305 | 306 | checkNone[JByte](GOption.absent[JByte].asScala) 307 | checkNone[JShort](GOption.absent[JShort].asScala) 308 | checkNone[JInt](GOption.absent[JInt].asScala) 309 | checkNone[JLong](GOption.absent[JLong].asScala) 310 | checkNone[JFloat](GOption.absent[JFloat].asScala) 311 | checkNone[JDouble](GOption.absent[JDouble].asScala) 312 | checkNone[JChar](GOption.absent[JChar].asScala) 313 | checkNone[JBoolean](GOption.absent[JBoolean].asScala) 314 | 315 | checkNone[A](GOption.absent[A].asScala) 316 | } 317 | 318 | "convert NOT nested options" in { 319 | val asScala = GOption.of(GOption.of[JDouble](2d)).asScala 320 | 321 | asScala shouldBe an[Option[_]] 322 | asScala.get shouldBe an[GOption[_]] 323 | 324 | GOption.of(GOption.of[JDouble](2d)).asScala: Option[GOption[JDouble]] 325 | } 326 | 327 | "convert NOT collections in options" in { 328 | val asScala = GOption.of(JSet[JDouble](2d)).asScala 329 | asScala shouldBe an[Option[_]] 330 | asScala.get shouldBe an[JSet[_]] 331 | 332 | GOption.of(JSet[JDouble](2d)).asScala: Option[JSet[JDouble]] 333 | } 334 | 335 | } 336 | 337 | } 338 | -------------------------------------------------------------------------------- /scalaj-google-optional/src/test/scala/com/daodecode/scalaj/googleoptional/test/ScalaJSpec.scala: -------------------------------------------------------------------------------- 1 | package com.daodecode.scalaj.googleoptional.test 2 | 3 | import org.scalatest.matchers.should.Matchers 4 | import org.scalatest.wordspec.AnyWordSpec 5 | 6 | trait ScalaJSpec extends AnyWordSpec with Matchers 7 | -------------------------------------------------------------------------------- /version.sbt: -------------------------------------------------------------------------------- 1 | ThisBuild / version := "0.3.3-SNAPSHOT" 2 | --------------------------------------------------------------------------------